mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-15 10:17:20 +00:00
Attempt to improve convergence of POSIX semaphore code with style(9).
MFC after: 3 days
This commit is contained in:
parent
9a55503ec1
commit
8e230e30b7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=179054
@ -72,7 +72,8 @@ static void sem_free(struct ksem *ksnew);
|
|||||||
static int sem_perm(struct thread *td, struct ksem *ks);
|
static int sem_perm(struct thread *td, struct ksem *ks);
|
||||||
static void sem_enter(struct proc *p, struct ksem *ks);
|
static void sem_enter(struct proc *p, struct ksem *ks);
|
||||||
static int sem_leave(struct proc *p, struct ksem *ks);
|
static int sem_leave(struct proc *p, struct ksem *ks);
|
||||||
static void sem_exechook(void *arg, struct proc *p, struct image_params *imgp);
|
static void sem_exechook(void *arg, struct proc *p,
|
||||||
|
struct image_params *imgp);
|
||||||
static void sem_exithook(void *arg, struct proc *p);
|
static void sem_exithook(void *arg, struct proc *p);
|
||||||
static void sem_forkhook(void *arg, struct proc *p1, struct proc *p2,
|
static void sem_forkhook(void *arg, struct proc *p1, struct proc *p2,
|
||||||
int flags);
|
int flags);
|
||||||
@ -89,21 +90,22 @@ static int kern_sem_open(struct thread *td, int dir, const char *name,
|
|||||||
static int kern_sem_unlink(struct thread *td, const char *name);
|
static int kern_sem_unlink(struct thread *td, const char *name);
|
||||||
|
|
||||||
#ifndef SEM_MAX
|
#ifndef SEM_MAX
|
||||||
#define SEM_MAX 30
|
#define SEM_MAX 30
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SEM_MAX_NAMELEN 14
|
#define SEM_MAX_NAMELEN 14
|
||||||
|
|
||||||
#define SEM_TO_ID(x) ((intptr_t)(x))
|
#define SEM_TO_ID(x) ((intptr_t)(x))
|
||||||
#define ID_TO_SEM(x) id_to_sem(x)
|
#define ID_TO_SEM(x) id_to_sem(x)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* available semaphores go here, this includes sem_init and any semaphores
|
* Available semaphores go here, this includes sem_init and any semaphores
|
||||||
* created via sem_open that have not yet been unlinked.
|
* created via sem_open that have not yet been unlinked.
|
||||||
*/
|
*/
|
||||||
LIST_HEAD(, ksem) ksem_head = LIST_HEAD_INITIALIZER(&ksem_head);
|
LIST_HEAD(, ksem) ksem_head = LIST_HEAD_INITIALIZER(&ksem_head);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* semaphores still in use but have been sem_unlink()'d go here.
|
* Semaphores still in use but have been sem_unlink()'d go here.
|
||||||
*/
|
*/
|
||||||
LIST_HEAD(, ksem) ksem_deadhead = LIST_HEAD_INITIALIZER(&ksem_deadhead);
|
LIST_HEAD(, ksem) ksem_deadhead = LIST_HEAD_INITIALIZER(&ksem_deadhead);
|
||||||
|
|
||||||
@ -117,13 +119,12 @@ SYSCTL_INT(_p1003_1b, OID_AUTO, nsems, CTLFLAG_RD, &nsems, 0, "");
|
|||||||
static eventhandler_tag sem_exit_tag, sem_exec_tag, sem_fork_tag;
|
static eventhandler_tag sem_exit_tag, sem_exec_tag, sem_fork_tag;
|
||||||
|
|
||||||
#ifdef SEM_DEBUG
|
#ifdef SEM_DEBUG
|
||||||
#define DP(x) printf x
|
#define DP(x) printf x
|
||||||
#else
|
#else
|
||||||
#define DP(x)
|
#define DP(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static __inline
|
static __inline void
|
||||||
void
|
|
||||||
sem_ref(struct ksem *ks)
|
sem_ref(struct ksem *ks)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -132,8 +133,7 @@ sem_ref(struct ksem *ks)
|
|||||||
DP(("sem_ref: ks = %p, ref = %d\n", ks, ks->ks_ref));
|
DP(("sem_ref: ks = %p, ref = %d\n", ks, ks->ks_ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline
|
static __inline void
|
||||||
void
|
|
||||||
sem_rel(struct ksem *ks)
|
sem_rel(struct ksem *ks)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -143,8 +143,6 @@ sem_rel(struct ksem *ks)
|
|||||||
sem_free(ks);
|
sem_free(ks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline struct ksem *id_to_sem(semid_t id);
|
|
||||||
|
|
||||||
static __inline
|
static __inline
|
||||||
struct ksem *
|
struct ksem *
|
||||||
id_to_sem(semid_t id)
|
id_to_sem(semid_t id)
|
||||||
@ -195,7 +193,8 @@ sem_create(struct thread *td, const char *name, struct ksem **ksret,
|
|||||||
free(ret, M_SEM);
|
free(ret, M_SEM);
|
||||||
return (ENAMETOOLONG);
|
return (ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
/* name must start with a '/' but not contain one. */
|
|
||||||
|
/* Name must start with a '/' but not contain one. */
|
||||||
if (*name != '/' || len < 2 || index(name + 1, '/') != NULL) {
|
if (*name != '/' || len < 2 || index(name + 1, '/') != NULL) {
|
||||||
free(ret, M_SEM);
|
free(ret, M_SEM);
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
@ -244,10 +243,8 @@ int ksem_init(struct thread *td, struct ksem_init_args *uap);
|
|||||||
int
|
int
|
||||||
ksem_init(struct thread *td, struct ksem_init_args *uap)
|
ksem_init(struct thread *td, struct ksem_init_args *uap)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
|
|
||||||
error = kern_sem_init(td, UIO_USERSPACE, uap->value, uap->idp);
|
return (kern_sem_init(td, UIO_USERSPACE, uap->value, uap->idp));
|
||||||
return (error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -317,6 +314,7 @@ kern_sem_open(struct thread *td, int dir, const char *name, int oflag,
|
|||||||
ksnew = NULL;
|
ksnew = NULL;
|
||||||
mtx_lock(&sem_lock);
|
mtx_lock(&sem_lock);
|
||||||
ks = sem_lookup_byname(name);
|
ks = sem_lookup_byname(name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we found it but O_EXCL is set, error.
|
* If we found it but O_EXCL is set, error.
|
||||||
*/
|
*/
|
||||||
@ -324,6 +322,7 @@ kern_sem_open(struct thread *td, int dir, const char *name, int oflag,
|
|||||||
mtx_unlock(&sem_lock);
|
mtx_unlock(&sem_lock);
|
||||||
return (EEXIST);
|
return (EEXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we didn't find it...
|
* If we didn't find it...
|
||||||
*/
|
*/
|
||||||
@ -335,6 +334,7 @@ kern_sem_open(struct thread *td, int dir, const char *name, int oflag,
|
|||||||
mtx_unlock(&sem_lock);
|
mtx_unlock(&sem_lock);
|
||||||
return (ENOENT);
|
return (ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We may block during creation, so drop the lock.
|
* We may block during creation, so drop the lock.
|
||||||
*/
|
*/
|
||||||
@ -357,6 +357,7 @@ kern_sem_open(struct thread *td, int dir, const char *name, int oflag,
|
|||||||
DP(("about to set! %d to %p\n", id, idp));
|
DP(("about to set! %d to %p\n", id, idp));
|
||||||
*idp = id;
|
*idp = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to make sure we haven't lost a race while
|
* We need to make sure we haven't lost a race while
|
||||||
* allocating during creation.
|
* allocating during creation.
|
||||||
@ -454,8 +455,6 @@ sem_free(struct ksem *ks)
|
|||||||
free(ks, M_SEM);
|
free(ks, M_SEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline struct kuser *sem_getuser(struct proc *p, struct ksem *ks);
|
|
||||||
|
|
||||||
static __inline struct kuser *
|
static __inline struct kuser *
|
||||||
sem_getuser(struct proc *p, struct ksem *ks)
|
sem_getuser(struct proc *p, struct ksem *ks)
|
||||||
{
|
{
|
||||||
@ -495,9 +494,7 @@ sem_leave(struct proc *p, struct ksem *ks)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sem_enter(p, ks)
|
sem_enter(struct proc *p, struct ksem *ks)
|
||||||
struct proc *p;
|
|
||||||
struct ksem *ks;
|
|
||||||
{
|
{
|
||||||
struct kuser *ku, *k;
|
struct kuser *ku, *k;
|
||||||
|
|
||||||
@ -584,7 +581,10 @@ kern_sem_close(struct thread *td, semid_t id)
|
|||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
mtx_lock(&sem_lock);
|
mtx_lock(&sem_lock);
|
||||||
ks = ID_TO_SEM(id);
|
ks = ID_TO_SEM(id);
|
||||||
/* this is not a valid operation for unnamed sems */
|
|
||||||
|
/*
|
||||||
|
* This is not a valid operation for unnamed sems.
|
||||||
|
*/
|
||||||
if (ks != NULL && ks->ks_name != NULL)
|
if (ks != NULL && ks->ks_name != NULL)
|
||||||
error = sem_leave(td->td_proc, ks);
|
error = sem_leave(td->td_proc, ks);
|
||||||
mtx_unlock(&sem_lock);
|
mtx_unlock(&sem_lock);
|
||||||
@ -661,7 +661,9 @@ ksem_timedwait(struct thread *td, struct ksem_timedwait_args *uap)
|
|||||||
struct timespec *ts;
|
struct timespec *ts;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* We allow a null timespec (wait forever). */
|
/*
|
||||||
|
* We allow a null timespec (wait forever).
|
||||||
|
*/
|
||||||
if (uap->abstime == NULL)
|
if (uap->abstime == NULL)
|
||||||
ts = NULL;
|
ts = NULL;
|
||||||
else {
|
else {
|
||||||
@ -885,6 +887,7 @@ sem_forkhook(void *arg, struct proc *p1, struct proc *p2, int flags)
|
|||||||
count = new_count;
|
count = new_count;
|
||||||
goto race_lost;
|
goto race_lost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given an array capable of storing an adequate number of semaphore
|
* Given an array capable of storing an adequate number of semaphore
|
||||||
* references, now walk the list of semaphores and acquire a new
|
* references, now walk the list of semaphores and acquire a new
|
||||||
@ -914,6 +917,7 @@ sem_forkhook(void *arg, struct proc *p1, struct proc *p2, int flags)
|
|||||||
}
|
}
|
||||||
mtx_unlock(&sem_lock);
|
mtx_unlock(&sem_lock);
|
||||||
KASSERT(i == count, ("sem_forkhook: i != count (%d, %d)", i, count));
|
KASSERT(i == count, ("sem_forkhook: i != count (%d, %d)", i, count));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now cause p2 to enter each of the referenced semaphores, then
|
* Now cause p2 to enter each of the referenced semaphores, then
|
||||||
* release our temporary reference. This is pretty inefficient.
|
* release our temporary reference. This is pretty inefficient.
|
||||||
@ -965,12 +969,14 @@ sem_modload(struct module *module, int cmd, void *arg)
|
|||||||
mtx_init(&sem_lock, "sem", "semaphore", MTX_DEF);
|
mtx_init(&sem_lock, "sem", "semaphore", MTX_DEF);
|
||||||
p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX);
|
p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX);
|
||||||
p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX);
|
p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX);
|
||||||
sem_exit_tag = EVENTHANDLER_REGISTER(process_exit, sem_exithook,
|
sem_exit_tag = EVENTHANDLER_REGISTER(process_exit,
|
||||||
NULL, EVENTHANDLER_PRI_ANY);
|
sem_exithook, NULL, EVENTHANDLER_PRI_ANY);
|
||||||
sem_exec_tag = EVENTHANDLER_REGISTER(process_exec, sem_exechook,
|
sem_exec_tag = EVENTHANDLER_REGISTER(process_exec,
|
||||||
NULL, EVENTHANDLER_PRI_ANY);
|
sem_exechook, NULL, EVENTHANDLER_PRI_ANY);
|
||||||
sem_fork_tag = EVENTHANDLER_REGISTER(process_fork, sem_forkhook, NULL, EVENTHANDLER_PRI_ANY);
|
sem_fork_tag = EVENTHANDLER_REGISTER(process_fork,
|
||||||
|
sem_forkhook, NULL, EVENTHANDLER_PRI_ANY);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_UNLOAD:
|
case MOD_UNLOAD:
|
||||||
if (nsems != 0) {
|
if (nsems != 0) {
|
||||||
error = EOPNOTSUPP;
|
error = EOPNOTSUPP;
|
||||||
@ -981,6 +987,7 @@ sem_modload(struct module *module, int cmd, void *arg)
|
|||||||
EVENTHANDLER_DEREGISTER(process_fork, sem_fork_tag);
|
EVENTHANDLER_DEREGISTER(process_fork, sem_fork_tag);
|
||||||
mtx_destroy(&sem_lock);
|
mtx_destroy(&sem_lock);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOD_SHUTDOWN:
|
case MOD_SHUTDOWN:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user