From 515ae0a3e99457904d85c2a4de36d869fc63dc76 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Tue, 10 Dec 2013 20:19:45 +0100 Subject: [PATCH] Change-Id: I0cf021813cb73a01b1c9f9a1b302bde1a2b4ff7e --- commands/ipcs/ipcs.c | 2 +- sys/sys/ipc.h | 62 ++++++++++++++-- sys/sys/sem.h | 172 ++++++++++++++++++++++++++++++++++++------- sys/sys/shm.h | 148 ++++++++++++++++++++++++++++--------- 4 files changed, 316 insertions(+), 68 deletions(-) diff --git a/commands/ipcs/ipcs.c b/commands/ipcs/ipcs.c index ed2d8f117..126a18cc8 100644 --- a/commands/ipcs/ipcs.c +++ b/commands/ipcs/ipcs.c @@ -98,7 +98,7 @@ union semun { #if defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 #define KEY __key #else -#define KEY key +#define KEY _key #endif #define LIMITS 1 diff --git a/sys/sys/ipc.h b/sys/sys/ipc.h index f6dddeb9b..b7931b109 100644 --- a/sys/sys/ipc.h +++ b/sys/sys/ipc.h @@ -51,17 +51,41 @@ #include #include -/* Data structure used to pass permission information to IPC operations. */ struct ipc_perm { - key_t key; /* Key. */ uid_t uid; /* user id */ gid_t gid; /* group id */ uid_t cuid; /* creator user id */ gid_t cgid; /* creator group id */ - unsigned short int mode; /* Reader/write permission. */ - unsigned short int __seq; /* Sequence number. */ + mode_t mode; /* r/w permission */ + + /* + * These members are private and used only in the internal + * implementation of this interface. + */ + unsigned short _seq; /* sequence # (to generate unique + msg/sem/shm id) */ + key_t _key; /* user specified msg/sem/shm key */ }; +#if defined(_NETBSD_SOURCE) +/* Warning: 64-bit structure padding is needed here */ +struct ipc_perm_sysctl { + uint64_t _key; + uid_t uid; + gid_t gid; + uid_t cuid; + gid_t cgid; + mode_t mode; + int16_t _seq; + int16_t pad; +}; +#endif /* _NETBSD_SOURCE */ + +/* Common access type bits, used with ipcperm(). */ +#define IPC_R 000400 /* read permission */ +#define IPC_W 000200 /* write/alter permission */ +#define IPC_M 010000 /* permission to change control info */ + /* X/Open required constants (same values as system 5) */ #define IPC_CREAT 001000 /* create entry if key does not exist */ #define IPC_EXCL 002000 /* fail if key exists */ @@ -74,7 +98,7 @@ struct ipc_perm { #define IPC_STAT 2 /* get options */ #ifdef __minix -#define IPC_INFO 3 /* See ipcs. */ +#define IPC_INFO 500 /* See ipcs. */ #endif /* !__minix */ /* @@ -86,10 +110,36 @@ struct ipc_perm { #define IXSEQ_TO_IPCID(ix,perm) (((perm._seq) << 16) | (ix & 0xffff)) #endif +#ifdef _KERNEL +#define IPCID_TO_IX(id) ((id) & 0xffff) +#define IPCID_TO_SEQ(id) (((id) >> 16) & 0xffff) + +struct kauth_cred; +int ipcperm(struct kauth_cred *, struct ipc_perm *, int); + +void sysvipcinit(void); + +/* + * sysctl helper routine for kern.ipc.sysvipc_info subtree. + */ + +#define SYSCTL_FILL_PERM(src, dst) do { \ + (dst)._key = (src)._key; \ + (dst).uid = (src).uid; \ + (dst).gid = (src).gid; \ + (dst).cuid = (src).cuid; \ + (dst).cgid = (src).cgid; \ + (dst).mode = (src).mode; \ + (dst)._seq = (src)._seq; \ +} while (/*CONSTCOND*/ 0); + +#endif /* _KERNEL */ + +#ifndef _KERNEL #include __BEGIN_DECLS key_t ftok(const char *, int); __END_DECLS - +#endif #endif /* !_SYS_IPC_H_ */ diff --git a/sys/sys/sem.h b/sys/sys/sem.h index 05971dde1..5807904e8 100644 --- a/sys/sys/sem.h +++ b/sys/sys/sem.h @@ -43,15 +43,26 @@ #include +#ifdef _KERNEL +struct __sem { + unsigned short semval; /* semaphore value */ + pid_t sempid; /* pid of last operation */ + unsigned short semncnt; /* # awaiting semval > cval */ + unsigned short semzcnt; /* # awaiting semval = 0 */ +}; +#endif /* _KERNEL */ + struct semid_ds { - struct ipc_perm sem_perm; /* operation permission struct */ - time_t sem_otime; /* last semop() time */ - unsigned long int __unused1; - time_t sem_ctime; /* last time changed by semctl() */ - unsigned long int __unused2; - unsigned long int sem_nsems; /* number of semaphores in set */ - unsigned long int __unused3; - unsigned long int __unused4; + struct ipc_perm sem_perm; /* operation permission structure */ + unsigned short sem_nsems; /* number of semaphores in set */ + time_t sem_otime; /* last semop() time */ + time_t sem_ctime; /* last time changed by semctl() */ + + /* + * These members are private and used only in the internal + * implementation of this interface. + */ + struct __sem *_sem_base; /* pointer to first semaphore in set */ }; /* @@ -62,25 +73,48 @@ struct sembuf { short sem_op; /* semaphore operation */ short sem_flg; /* operation flags */ }; -#define SEM_UNDO 0x1000 /* undo changes on process exit */ +#define SEM_UNDO 010000 /* undo changes on process exit */ /* * commands for semctl */ -#define GETPID 11 /* get sempid */ -#define GETVAL 12 /* get semval */ -#define GETALL 13 /* get all semval's */ -#define GETNCNT 14 /* get semncnt */ -#define GETZCNT 15 /* get semzcnt */ -#define SETVAL 16 /* set semval */ -#define SETALL 17 /* set all semval's */ +#define GETNCNT 3 /* Return the value of semncnt {READ} */ +#define GETPID 4 /* Return the value of sempid {READ} */ +#define GETVAL 5 /* Return the value of semval {READ} */ +#define GETALL 6 /* Return semvals into arg.array {READ} */ +#define GETZCNT 7 /* Return the value of semzcnt {READ} */ +#define SETVAL 8 /* Set the value of semval to arg.val {ALTER} */ +#define SETALL 9 /* Set semvals from arg.array {ALTER} */ -#ifdef __USE_MISC +#if defined(_KERNEL) || defined(__minix) +/* + * Kernel implementation stuff + */ +#define SEMVMX 32767 /* semaphore maximum value */ +#define SEMAEM 16384 /* adjust on exit max value */ -/* ipcs ctl cmds */ -# define SEM_STAT 18 -# define SEM_INFO 19 +/* + * Permissions + */ +#define SEM_A 0200 /* alter permission */ +#define SEM_R 0400 /* read permission */ +/* + * Undo structure (one per process) + */ +struct sem_undo { + struct sem_undo *un_next; /* ptr to next active undo structure */ + struct proc *un_proc; /* owner of this structure */ + short un_cnt; /* # of active entries */ + struct undo { + short un_adjval; /* adjust on exit values */ + short un_num; /* semaphore # */ + int un_id; /* semid */ + } un_ent[1]; /* undo entries */ +}; +#endif /* _KERNEL */ + +#if defined(_NETBSD_SOURCE) /* * semaphore info struct */ @@ -97,25 +131,109 @@ struct seminfo { int32_t semaem; /* adjust on exit max value */ }; -#endif /* __USE_MISC */ +/* Warning: 64-bit structure padding is needed here */ +struct semid_ds_sysctl { + struct ipc_perm_sysctl sem_perm; + int16_t sem_nsems; + int16_t pad2; + int32_t pad3; + time_t sem_otime; + time_t sem_ctime; +}; +struct sem_sysctl_info { + struct seminfo seminfo; + struct semid_ds_sysctl semids[1]; +}; + +/* + * Internal "mode" bits. The first of these is used by ipcs(1), and so + * is defined outside the kernel as well. + */ +#define SEM_ALLOC 01000 /* semaphore is allocated */ +#endif /* !_POSIX_C_SOURCE && !_XOPEN_SOURCE */ + +#if defined(_KERNEL) || defined(__minix) +#define SEM_DEST 02000 /* semaphore will be destroyed on last detach */ /* * Configuration parameters */ -#define SEMMNI 128 -#define SEMMSL 250 -#define SEMMNS (SEMMSL*SEMMNI) +#ifndef SEMMNI +#define SEMMNI 10 /* # of semaphore identifiers */ +#endif +#ifndef SEMMNS +#define SEMMNS 60 /* # of semaphores in system */ +#endif +#ifndef SEMUME +#define SEMUME 10 /* max # of undo entries per process */ +#endif +#ifndef SEMMNU +#define SEMMNU 30 /* # of undo structures in system */ +#endif -#define SEMOPM 32 -#define SEMVMX 32767 +/* shouldn't need tuning */ +#ifndef SEMMAP +#define SEMMAP 30 /* # of entries in semaphore map */ +#endif +#ifndef SEMMSL +#define SEMMSL SEMMNS /* max # of semaphores per id */ +#endif +#ifndef SEMOPM +#define SEMOPM 100 /* max # of operations per semop call */ +#endif +/* actual size of an undo structure */ +#define SEMUSZ (sizeof(struct sem_undo)+sizeof(struct undo)*SEMUME) +/* + * Structures allocated in machdep.c + */ +extern struct seminfo seminfo; +extern struct semid_ds *sema; /* semaphore id pool */ + +/* + * Parameters to the semconfig system call + */ +#define SEM_CONFIG_FREEZE 0 /* Freeze the semaphore facility. */ +#define SEM_CONFIG_THAW 1 /* Thaw the semaphore facility. */ + +#define SYSCTL_FILL_SEM(src, dst) do { \ + SYSCTL_FILL_PERM((src).sem_perm, (dst).sem_perm); \ + (dst).sem_nsems = (src).sem_nsems; \ + (dst).sem_otime = (src).sem_otime; \ + (dst).sem_ctime = (src).sem_ctime; \ +} while (/*CONSTCOND*/ 0) + +#endif /* _KERNEL */ + +#ifdef __minix +/* ipcs ctl cmds */ +# define SEM_STAT 18 +# define SEM_INFO 19 +#endif + +#ifndef _KERNEL #include __BEGIN_DECLS -int semctl(int, int, int, ...); +#ifndef __LIBC12_SOURCE__ +int semctl(int, int, int, ...) __RENAME(__semctl50); +#endif int semget(key_t, int, int); int semop(int, struct sembuf *, size_t); +#if defined(_NETBSD_SOURCE) +int semconfig(int); +#endif __END_DECLS +#else +void seminit(void); +void semexit(struct proc *, void *); + +int semctl1(struct lwp *, int, int, int, void *, register_t *); +#define get_semctl_arg(cmd, sembuf, arg) \ + ((cmd) == IPC_SET || (cmd) == IPC_STAT ? (void *)sembuf \ + : (cmd) == GETALL || (cmd) == SETVAL || (cmd) == SETALL ? (void *)arg \ + : NULL) +#endif /* !_KERNEL */ #endif /* !_SYS_SEM_H_ */ diff --git a/sys/sys/shm.h b/sys/sys/shm.h index 2003c72af..66d87747f 100644 --- a/sys/sys/shm.h +++ b/sys/sys/shm.h @@ -75,69 +75,121 @@ #define SHM_RDONLY 010000 /* Attach read-only (else read-write) */ #define SHM_RND 020000 /* Round attach address to SHMLBA */ +#ifdef _KERNEL +#define _SHM_RMLINGER 040000 /* Attach even if segment removed */ +#endif /* Segment low boundry address multiple */ -#define SHMLBA getpagesize() -#define SHMMNI 4096 -#define SHMSEG 32 /* max shared segs per process */ +#if defined(_KERNEL) || defined(_STANDALONE) || defined(_MODULE) +#define SHMLBA PAGE_SIZE +#else +/* + * SHMLBA uses libc's internal __sysconf() to retrieve the machine's + * page size. The value of _SC_PAGESIZE is 28 -- we hard code it so we do not + * need to include unistd.h + */ +__BEGIN_DECLS +long __sysconf(int); +__END_DECLS +#define SHMLBA (__sysconf(28)) +#endif typedef unsigned int shmatt_t; struct shmid_ds { struct ipc_perm shm_perm; /* operation permission structure */ size_t shm_segsz; /* size of segment in bytes */ + pid_t shm_lpid; /* process ID of last shm operation */ + pid_t shm_cpid; /* process ID of creator */ + shmatt_t shm_nattch; /* number of current attaches */ time_t shm_atime; /* time of last shmat() */ time_t shm_dtime; /* time of last shmdt() */ time_t shm_ctime; /* time of last change by shmctl() */ - pid_t shm_cpid; /* process ID of creator */ - pid_t shm_lpid; /* process ID of last shm operation */ - shmatt_t shm_nattch; /* number of current attaches */ + + /* + * These members are private and used only in the internal + * implementation of this interface. + */ + void *_shm_internal; }; +#if defined(_NETBSD_SOURCE) +/* + * Some systems (e.g. HP-UX) take these as the second (cmd) arg to shmctl(). + */ +#define SHM_LOCK 3 /* Lock segment in memory. */ +#define SHM_UNLOCK 4 /* Unlock a segment locked by SHM_LOCK. */ +#endif /* _NETBSD_SOURCE */ -/* shm_mode upper byte flags */ -#define SHM_DEST 01000 /* segment will be destroyed on last detach */ -#define SHM_LOCKED 02000 /* segment will not be swapped */ - -/* ipcs ctl commands */ -#define SHM_STAT 13 -#define SHM_INFO 14 - - -#if defined(_NETBSD_SOURCE) || defined(__minix) +#if defined(_NETBSD_SOURCE) /* * Permission definitions used in shmflag arguments to shmat(2) and shmget(2). * Provided for source compatibility only; do not use in new code! */ -#define SHM_R 0400 -#define SHM_W 0200 +#define SHM_R IPC_R /* S_IRUSR, R for owner */ +#define SHM_W IPC_W /* S_IWUSR, W for owner */ /* * System 5 style catch-all structure for shared memory constants that * might be of interest to user programs. Do we really want/need this? */ struct shminfo { - unsigned long int shmmax; /* max shared memory segment size (bytes) */ - unsigned long int shmmin; /* min shared memory segment size (bytes) */ - unsigned long int shmmni; /* max number of shared memory identifiers */ - unsigned long int shmseg; /* max shared memory segments per process */ - unsigned long int shmall; /* max amount of shared memory (pages) */ + uint64_t shmmax; /* max shared memory segment size (bytes) */ + uint32_t shmmin; /* min shared memory segment size (bytes) */ + uint32_t shmmni; /* max number of shared memory identifiers */ + uint32_t shmseg; /* max shared memory segments per process */ + uint32_t shmall; /* max amount of shared memory (pages) */ }; -#ifdef __minix -struct shm_info -{ - int used_ids; - unsigned long int shm_tot; /* total allocated shm */ - unsigned long int shm_rss; /* total resident shm */ - unsigned long int shm_swp; /* total swapped shm */ - unsigned long int swap_attempts; - unsigned long int swap_successes; +/* Warning: 64-bit structure padding is needed here */ +struct shmid_ds_sysctl { + struct ipc_perm_sysctl shm_perm; + uint64_t shm_segsz; + pid_t shm_lpid; + pid_t shm_cpid; + time_t shm_atime; + time_t shm_dtime; + time_t shm_ctime; + uint32_t shm_nattch; +}; +struct shm_sysctl_info { + struct shminfo shminfo; + struct shmid_ds_sysctl shmids[1]; }; -#endif /* __minix */ - #endif /* _NETBSD_SOURCE */ +#ifdef _KERNEL +extern struct shminfo shminfo; +extern struct shmid_ds *shmsegs; +extern int shm_nused; + +#define SHMSEG_FREE 0x0200 +#define SHMSEG_REMOVED 0x0400 +#define SHMSEG_ALLOCATED 0x0800 +#define SHMSEG_WANTED 0x1000 +#define SHMSEG_RMLINGER 0x2000 +#define SHMSEG_WIRED 0x4000 + +struct vmspace; + +void shminit(void); +void shmfork(struct vmspace *, struct vmspace *); +void shmexit(struct vmspace *); +int shmctl1(struct lwp *, int, int, struct shmid_ds *); + +#define SYSCTL_FILL_SHM(src, dst) do { \ + SYSCTL_FILL_PERM((src).shm_perm, (dst).shm_perm); \ + (dst).shm_segsz = (src).shm_segsz; \ + (dst).shm_lpid = (src).shm_lpid; \ + (dst).shm_cpid = (src).shm_cpid; \ + (dst).shm_atime = (src).shm_atime; \ + (dst).shm_dtime = (src).shm_dtime; \ + (dst).shm_ctime = (src).shm_ctime; \ + (dst).shm_nattch = (src).shm_nattch; \ +} while (/*CONSTCOND*/ 0) + +#else /* !_KERNEL */ + __BEGIN_DECLS void *shmat(int, const void *, int); int shmctl(int, int, struct shmid_ds *) __RENAME(__shmctl50); @@ -145,4 +197,32 @@ int shmdt(const void *); int shmget(key_t, size_t, int); __END_DECLS +#endif /* !_KERNEL */ + +#ifdef __minix +/* ipcs ctl commands */ +#define SHM_STAT 13 +#define SHM_INFO 14 +#endif + +#ifdef __minix +struct shm_info +{ + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; +}; + +#define SHMMNI 4096 +#define SHMSEG 32 /* max shared segs per process */ + +/* shm_mode upper byte flags */ +#define SHM_DEST 01000 /* segment will be destroyed on last detach */ +#define SHM_LOCKED 02000 /* segment will not be swapped */ + +#endif + #endif /* !_SYS_SHM_H_ */