From e7974541d02e3603d59bd82caebea23eb97bd6b4 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Tue, 25 Feb 2014 14:24:52 +0100 Subject: [PATCH] Rearrange endpoint number layout The constants ANY, NONE, and SELF are now a function of the way the endpoint number is split between a generation number and a process slot number, rather than the other way around. This allows for the use of bit masking and shifting instead of the previous (and more expensive) multiplication and division. Change-Id: Id890eea74435444128c75eb0c89816b948f43c0b --- include/lib.h | 2 +- include/minix/com.h | 18 ----------- include/minix/endpoint.h | 67 +++++++++++++++++++++++++++++++++------- test/test39.c | 2 +- 4 files changed, 57 insertions(+), 32 deletions(-) diff --git a/include/lib.h b/include/lib.h index f3df2951f..e5e1d2582 100644 --- a/include/lib.h +++ b/include/lib.h @@ -18,7 +18,7 @@ #include #include #include - +#include #include struct ps_strings; /* forward declaration for minix_stack_fill. */ diff --git a/include/minix/com.h b/include/minix/com.h index d63545452..219345c0a 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -35,28 +35,10 @@ #ifndef _MINIX_COM_H #define _MINIX_COM_H -/*===========================================================================* - * Magic process numbers * - *===========================================================================*/ - -/* These may not be any valid endpoint (see ). */ -#define ANY ((endpoint_t) 0x7ace) /* used to indicate 'any process' */ -#define NONE ((endpoint_t) 0x6ace) /* used to indicate 'no process at all' */ -#define SELF ((endpoint_t) 0x8ace) /* used to indicate 'own process' */ -#define _MAX_MAGIC_PROC (SELF) /* used by - to determine generation size */ - /*===========================================================================* * Process numbers of processes in the system image * *===========================================================================*/ -/* The values of several task numbers depend on whether they or other tasks - * are enabled. They are defined as (PREVIOUS_TASK - ENABLE_TASK) in general. - * ENABLE_TASK is either 0 or 1, so a task either gets a new number, or gets - * the same number as the previous task and is further unused. Note that the - * order should correspond to the order in the task table defined in table.c. - */ - /* Kernel tasks. These all run in the same address space. */ #define ASYNCM ((endpoint_t) -5) /* notifies about finished async sends */ #define IDLE ((endpoint_t) -4) /* runs when no one else can run */ diff --git a/include/minix/endpoint.h b/include/minix/endpoint.h index 54dc7b9d6..0cf3f3bb7 100644 --- a/include/minix/endpoint.h +++ b/include/minix/endpoint.h @@ -7,22 +7,65 @@ #include #include -/* The point of the padding in 'generation size' is to - * allow for certain bogus endpoint numbers such as NONE, ANY, etc. +/* + * Endpoints are split into two parts: a process slot and a generation number. * - * The _MAX_MAGIC_PROC is defined by . That include - * file defines some magic process numbers such as ANY and NONE, - * and must never be a valid endpoint number. Therefore we make sure - * the generation size is big enough to start the next generation - * above the highest magic number. + * The process slot number identifies the slot in various process tables. + * It is positive or zero for user processes, and negative for kernel tasks. + * Constants dictate that with the current endpoint layout, the maximum range + * of process slot numbers is [-MAX_NR_TASKS,MAX_NR_PROCS>. The used part of + * the range is currently [-NR_TASKS,NR_PROCS> -- these two constants may be + * changed within the maximum range without changing the endpoint layout. + * + * The generation number is a per-slot number that gets increased by one every + * time a slot is reused for a new process. The generation number minimizes + * the chance that the endpoint of a dead process can (accidentially) be used + * to communicate with a different, live process. Preventing such accidents + * is essential for proper system service restartability support. + * + * The split between the two parts of the endpoint is such that when the + * generation number is zero, the endpoint number equals the process slot + * number, even for negative task numbers. This is required for the endpoint + * numbers hardcoded in , and it makes endpoint numbers easy to + * read in general. + * + * There are three special endpoint numbers: ANY, NONE, and SELF. These + * numbers are used to identify "any process", "no process at all", and + * "own process", respectively. They fall outside the normal range of + * process slot numbers, and are always of generation zero. */ -#define _ENDPOINT_GENERATION_SIZE (MAX_NR_TASKS+_MAX_MAGIC_PROC+1) -#define _ENDPOINT_MAX_GENERATION (INT_MAX/_ENDPOINT_GENERATION_SIZE-1) + +/* + * The following constant defines the split between the two parts of the + * endpoint numbers. It can be adjusted to allow for either more processes + * or more per-process generation numbers. Changing it will change the + * endpoint number layout, and thus break binary compatibility with existing + * processes. + */ +#define _ENDPOINT_GENERATION_SHIFT 15 + +/* Derived constants. */ +#define _ENDPOINT_GENERATION_SIZE (1 << _ENDPOINT_GENERATION_SHIFT) +/* INT_MAX is used here to prevent signedness issues with the macros below. */ +#define _ENDPOINT_MAX_GENERATION (INT_MAX/_ENDPOINT_GENERATION_SIZE-1) +#define _ENDPOINT_SLOT_TOP (_ENDPOINT_GENERATION_SIZE-MAX_NR_TASKS) + +/* The special endpoint numbers, and the resulting maximum slot number. */ +#define ANY ((endpoint_t) (_ENDPOINT_SLOT_TOP - 1)) +#define NONE ((endpoint_t) (_ENDPOINT_SLOT_TOP - 2)) +#define SELF ((endpoint_t) (_ENDPOINT_SLOT_TOP - 3)) +#define MAX_NR_PROCS (_ENDPOINT_SLOT_TOP - 3) /* (int)SELF */ + +/* Sanity check. */ +#if NR_PROCS > MAX_NR_PROCS +#error "NR_PROCS exceeds MAX_NR_PROCS, increase _ENDPOINT_GENERATION_SHIFT" +#endif /* Generation + Process slot number <-> endpoint. */ -#define _ENDPOINT(g, p) ((endpoint_t)((g) * _ENDPOINT_GENERATION_SIZE + (p))) -#define _ENDPOINT_G(e) (((e)+MAX_NR_TASKS) / _ENDPOINT_GENERATION_SIZE) +#define _ENDPOINT(g, p) \ + ((endpoint_t)(((g) << _ENDPOINT_GENERATION_SHIFT) + (p))) +#define _ENDPOINT_G(e) (((e)+MAX_NR_TASKS) >> _ENDPOINT_GENERATION_SHIFT) #define _ENDPOINT_P(e) \ - ((((e)+MAX_NR_TASKS) % _ENDPOINT_GENERATION_SIZE) - MAX_NR_TASKS) + ((((e)+MAX_NR_TASKS) & (_ENDPOINT_GENERATION_SIZE - 1)) - MAX_NR_TASKS) #endif diff --git a/test/test39.c b/test/test39.c index 05b143e94..0ec2931c3 100644 --- a/test/test39.c +++ b/test/test39.c @@ -23,7 +23,7 @@ void test39a() subtest = 1; for (g = 0; g <= _ENDPOINT_MAX_GENERATION; g++) { - for (p = -MAX_NR_TASKS; p < _NR_PROCS; p++) { + for (p = -MAX_NR_TASKS; p < MAX_NR_PROCS; p++) { endpoint_t ept; int mg, mp; ept = _ENDPOINT(g, p);