Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Change the way semid_t values are chosen. Instead of us...
details: https://anonhg.NetBSD.org/src/rev/4b6ee64576e1
branches: trunk
changeset: 588876:4b6ee64576e1
user: cube <cube%NetBSD.org@localhost>
date: Sun Mar 05 00:49:19 2006 +0000
description:
Change the way semid_t values are chosen. Instead of using kernel
addresses, use a uint32_t counter and the machinery to properly use it.
That makes the ksem_* system calls friendly for COMPAT_NETBSD32.
OK'd by thorpej@.
diffstat:
sys/kern/uipc_sem.c | 89 +++++++++++++++++++++++++++++++++++++++++++---------
sys/sys/ksem.h | 6 ++-
2 files changed, 78 insertions(+), 17 deletions(-)
diffs (268 lines):
diff -r 4d0918b0f4c5 -r 4b6ee64576e1 sys/kern/uipc_sem.c
--- a/sys/kern/uipc_sem.c Sun Mar 05 00:32:43 2006 +0000
+++ b/sys/kern/uipc_sem.c Sun Mar 05 00:49:19 2006 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_sem.c,v 1.12 2005/12/24 19:12:23 perry Exp $ */
+/* $NetBSD: uipc_sem.c,v 1.13 2006/03/05 00:49:19 cube Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_sem.c,v 1.12 2005/12/24 19:12:23 perry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_sem.c,v 1.13 2006/03/05 00:49:19 cube Exp $");
#include "opt_posix.h"
@@ -89,8 +89,10 @@
#define SEM_MAX_NAMELEN 14
#define SEM_VALUE_MAX (~0U)
+#define SEM_HASHTBL_SIZE 13
-#define SEM_TO_ID(x) ((intptr_t)(x))
+#define SEM_TO_ID(x) (((x)->ks_id))
+#define SEM_HASH(id) ((id) % SEM_HASHTBL_SIZE)
MALLOC_DEFINE(M_SEM, "p1003_1b_sem", "p1003_1b semaphores");
@@ -101,6 +103,7 @@
*/
struct ksem {
LIST_ENTRY(ksem) ks_entry; /* global list entry */
+ LIST_ENTRY(ksem) ks_hash; /* hash list entry */
struct simplelock ks_interlock; /* lock on this ksem */
char *ks_name; /* if named, this is the name */
unsigned int ks_ref; /* number of references */
@@ -109,6 +112,7 @@
gid_t ks_gid; /* creator gid */
unsigned int ks_value; /* current value */
unsigned int ks_waiters; /* number of waiters */
+ semid_t ks_id; /* unique identifier */
};
struct ksem_ref {
@@ -121,14 +125,24 @@
LIST_HEAD(, ksem_ref) kp_ksems;
};
+LIST_HEAD(ksem_list, ksem);
+
/*
* ksem_slock protects ksem_head and nsems. Only named semaphores go
* onto ksem_head.
*/
static struct simplelock ksem_slock;
-static LIST_HEAD(, ksem) ksem_head = LIST_HEAD_INITIALIZER(&ksem_head);
+static struct ksem_list ksem_head = LIST_HEAD_INITIALIZER(&ksem_head);
+static struct ksem_list ksem_hash[SEM_HASHTBL_SIZE];
static int nsems = 0;
+/*
+ * ksem_counter is the last assigned semid_t. It needs to be COMPAT_NETBSD32
+ * friendly, even though semid_t itself is defined as uintptr_t.
+ */
+static uint32_t ksem_counter = 1;
+
+
static void
ksem_free(struct ksem *ks)
{
@@ -140,11 +154,13 @@
*/
if (ks->ks_name == NULL) {
simple_unlock(&ks->ks_interlock);
- free(ks, M_SEM);
simple_lock(&ksem_slock);
nsems--;
+ LIST_REMOVE(ks, ks_hash);
simple_unlock(&ksem_slock);
+
+ free(ks, M_SEM);
return;
}
simple_unlock(&ks->ks_interlock);
@@ -239,6 +255,19 @@
}
static struct ksem *
+ksem_lookup_byid(semid_t id)
+{
+ struct ksem *ks;
+
+ LOCK_ASSERT(simple_lock_held(&ksem_slock));
+ LIST_FOREACH(ks, &ksem_hash[SEM_HASH(id)], ks_hash) {
+ if (ks->ks_id == id)
+ return ks;
+ }
+ return NULL;
+}
+
+static struct ksem *
ksem_lookup_byname(const char *name)
{
struct ksem *ks;
@@ -297,6 +326,14 @@
return (ENFILE);
}
nsems++;
+ while (ksem_lookup_byid(ksem_counter) != NULL) {
+ ksem_counter++;
+ /* 0 is a special value for libpthread */
+ if (ksem_counter == 0)
+ ksem_counter++;
+ }
+ ret->ks_id = ksem_counter;
+ LIST_INSERT_HEAD(&ksem_hash[SEM_HASH(ret->ks_id)], ret, ks_hash);
simple_unlock(&ksem_slock);
*ksret = ret;
@@ -310,16 +347,24 @@
unsigned int value;
semid_t *idp;
} */ *uap = v;
+
+ return do_ksem_init(l, SCARG(uap, value), SCARG(uap, idp), copyout);
+}
+
+int
+do_ksem_init(struct lwp *l, unsigned int value, semid_t *idp,
+ copyout_t docopyout)
+{
struct ksem *ks;
semid_t id;
int error;
/* Note the mode does not matter for anonymous semaphores. */
- error = ksem_create(l->l_proc, NULL, &ks, 0, SCARG(uap, value));
+ error = ksem_create(l->l_proc, NULL, &ks, 0, value);
if (error)
return (error);
id = SEM_TO_ID(ks);
- error = copyout(&id, SCARG(uap, idp), sizeof(id));
+ error = (*docopyout)(&id, idp, sizeof(id));
if (error) {
simple_lock(&ks->ks_interlock);
ksem_delref(ks);
@@ -341,13 +386,22 @@
unsigned int value;
semid_t *idp;
} */ *uap = v;
+
+ return do_ksem_open(l, SCARG(uap, name), SCARG(uap, oflag),
+ SCARG(uap, mode), SCARG(uap, value), SCARG(uap, idp), copyout);
+}
+
+int
+do_ksem_open(struct lwp *l, const char *semname, int oflag, mode_t mode,
+ unsigned int value, semid_t *idp, copyout_t docopyout)
+{
char name[SEM_MAX_NAMELEN + 1];
size_t done;
int error;
struct ksem *ksnew, *ks;
semid_t id;
- error = copyinstr(SCARG(uap, name), name, sizeof(name), &done);
+ error = copyinstr(semname, name, sizeof(name), &done);
if (error)
return (error);
@@ -358,7 +412,7 @@
/* Found one? */
if (ks != NULL) {
/* Check for exclusive create. */
- if (SCARG(uap, oflag) & O_EXCL) {
+ if (oflag & O_EXCL) {
simple_unlock(&ks->ks_interlock);
simple_unlock(&ksem_slock);
return (EEXIST);
@@ -378,7 +432,7 @@
return (error);
id = SEM_TO_ID(ks);
- error = copyout(&id, SCARG(uap, idp), sizeof(id));
+ error = (*docopyout)(&id, idp, sizeof(id));
if (error) {
simple_lock(&ks->ks_interlock);
ksem_delref(ks);
@@ -393,7 +447,7 @@
/*
* didn't ask for creation? error.
*/
- if ((SCARG(uap, oflag) & O_CREAT) == 0) {
+ if ((oflag & O_CREAT) == 0) {
simple_unlock(&ksem_slock);
return (ENOENT);
}
@@ -402,13 +456,12 @@
* We may block during creation, so drop the lock.
*/
simple_unlock(&ksem_slock);
- error = ksem_create(l->l_proc, name, &ksnew, SCARG(uap, mode),
- SCARG(uap, value));
+ error = ksem_create(l->l_proc, name, &ksnew, mode, value);
if (error != 0)
return (error);
id = SEM_TO_ID(ksnew);
- error = copyout(&id, SCARG(uap, idp), sizeof(id));
+ error = (*docopyout)(&id, idp, sizeof(id));
if (error) {
free(ksnew->ks_name, M_SEM);
ksnew->ks_name = NULL;
@@ -424,7 +477,7 @@
*/
simple_lock(&ksem_slock);
if ((ks = ksem_lookup_byname(name)) != NULL) {
- if (SCARG(uap, oflag) & O_EXCL) {
+ if (oflag & O_EXCL) {
simple_unlock(&ks->ks_interlock);
simple_unlock(&ksem_slock);
@@ -453,7 +506,7 @@
struct ksem_ref *ksr;
LIST_FOREACH(ksr, &kp->kp_ksems, ksr_list) {
- if (id == (semid_t) ksr->ksr_ksem) {
+ if (id == SEM_TO_ID(ksr->ksr_ksem)) {
simple_lock(&ksr->ksr_ksem->ks_interlock);
return (ksr->ksr_ksem);
}
@@ -748,9 +801,13 @@
void
ksem_init(void)
{
+ int i;
simple_lock_init(&ksem_slock);
exithook_establish(ksem_exithook, NULL);
exechook_establish(ksem_exithook, NULL);
forkhook_establish(ksem_forkhook);
+
+ for (i = 0; i < SEM_HASHTBL_SIZE; i++)
+ LIST_INIT(&ksem_hash[i]);
}
diff -r 4d0918b0f4c5 -r 4b6ee64576e1 sys/sys/ksem.h
--- a/sys/sys/ksem.h Sun Mar 05 00:32:43 2006 +0000
+++ b/sys/sys/ksem.h Sun Mar 05 00:49:19 2006 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ksem.h,v 1.5 2005/12/11 12:25:20 christos Exp $ */
+/* $NetBSD: ksem.h,v 1.6 2006/03/05 00:49:19 cube Exp $ */
/*
* Copyright (c) 2002 Alfred Perlstein <alfred%FreeBSD.org@localhost>
@@ -33,6 +33,10 @@
#ifdef _KERNEL
void ksem_init(void);
+
+int do_ksem_init(struct lwp *, unsigned int, semid_t *, copyout_t);
+int do_ksem_open(struct lwp *, const char *, int, mode_t, unsigned int,
+ semid_t *, copyout_t);
#endif
#ifdef _LIBC
Home |
Main Index |
Thread Index |
Old Index