IPC server: restyle
Closer to KNF, better coding practices, more similar to other services, no more global variables, a few more comments, that kind of stuff. No major functional changes. Change-Id: I6e8f53bfafd6f41e92031fba76c40a31d2107a8e
This commit is contained in:
parent
4d272e5a97
commit
0baafa0ef4
@ -11,6 +11,7 @@
|
|||||||
#include <minix/syslib.h>
|
#include <minix/syslib.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
#include <sys/sem.h>
|
#include <sys/sem.h>
|
||||||
@ -38,17 +39,20 @@
|
|||||||
#define IPCID_TO_IX(id) ((id) & 0xffff)
|
#define IPCID_TO_IX(id) ((id) & 0xffff)
|
||||||
#define IPCID_TO_SEQ(id) (((id) >> 16) & 0xffff)
|
#define IPCID_TO_SEQ(id) (((id) >> 16) & 0xffff)
|
||||||
|
|
||||||
|
/* shm.c */
|
||||||
int do_shmget(message *);
|
int do_shmget(message *);
|
||||||
int do_shmat(message *);
|
int do_shmat(message *);
|
||||||
int do_shmdt(message *);
|
int do_shmdt(message *);
|
||||||
int do_shmctl(message *);
|
int do_shmctl(message *);
|
||||||
int check_perm(struct ipc_perm *, endpoint_t, int);
|
int is_shm_nil(void);
|
||||||
void update_refcount_and_destroy(void);
|
void update_refcount_and_destroy(void);
|
||||||
|
|
||||||
|
/* sem.c */
|
||||||
int do_semget(message *);
|
int do_semget(message *);
|
||||||
int do_semctl(message *);
|
int do_semctl(message *);
|
||||||
int do_semop(message *);
|
int do_semop(message *);
|
||||||
int is_sem_nil(void);
|
int is_sem_nil(void);
|
||||||
int is_shm_nil(void);
|
|
||||||
void sem_process_vm_notify(void);
|
void sem_process_vm_notify(void);
|
||||||
|
|
||||||
EXTERN endpoint_t who_e;
|
/* utility.c */
|
||||||
|
int check_perm(struct ipc_perm *, endpoint_t, int);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
endpoint_t who_e;
|
/*
|
||||||
static unsigned int call_type;
|
* The call table for this service.
|
||||||
|
*/
|
||||||
#define CALL(n) [((n) - IPC_BASE)]
|
#define CALL(n) [((n) - IPC_BASE)]
|
||||||
static int (* const call_vec[])(message *) = {
|
static int (* const call_vec[])(message *) = {
|
||||||
CALL(IPC_SHMGET) = do_shmget,
|
CALL(IPC_SHMGET) = do_shmget,
|
||||||
@ -16,125 +16,122 @@ static int (* const call_vec[])(message *) = {
|
|||||||
|
|
||||||
static int verbose = 0;
|
static int verbose = 0;
|
||||||
|
|
||||||
/* SEF functions and variables. */
|
/*
|
||||||
static void sef_local_startup(void);
|
* Initialize the IPC server.
|
||||||
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
*/
|
||||||
static void sef_cb_signal_handler(int signo);
|
static int
|
||||||
|
sef_cb_init_fresh(int type __unused, sef_init_info_t * info __unused)
|
||||||
|
{
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sef_cb_signal_handler(int signo)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Only check for termination signal, ignore anything else. */
|
||||||
|
if (signo != SIGTERM) return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if there are still IPC keys around. If not, we can safely
|
||||||
|
* exit immediately. Otherwise, warn the system administrator.
|
||||||
|
*/
|
||||||
|
if (is_sem_nil() && is_shm_nil())
|
||||||
|
sef_exit(0);
|
||||||
|
|
||||||
|
printf("IPC: exit with unclean state\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sef_local_startup(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Register init callbacks. */
|
||||||
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||||
|
sef_setcb_init_restart(sef_cb_init_fresh);
|
||||||
|
|
||||||
|
/* Register signal callbacks. */
|
||||||
|
sef_setcb_signal_handler(sef_cb_signal_handler);
|
||||||
|
|
||||||
|
/* Let SEF perform startup. */
|
||||||
|
sef_startup();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char ** argv)
|
||||||
{
|
{
|
||||||
message m;
|
message m;
|
||||||
unsigned int ipc_number;
|
unsigned int call_index;
|
||||||
int r;
|
int r, ipc_status;
|
||||||
|
|
||||||
/* SEF local startup. */
|
/* SEF local startup. */
|
||||||
env_setargs(argc, argv);
|
env_setargs(argc, argv);
|
||||||
sef_local_startup();
|
sef_local_startup();
|
||||||
|
|
||||||
while (TRUE) {
|
/* The main message loop. */
|
||||||
if ((r = sef_receive(ANY, &m)) != OK)
|
for (;;) {
|
||||||
printf("sef_receive failed %d.\n", r);
|
if ((r = sef_receive_status(ANY, &m, &ipc_status)) != OK)
|
||||||
who_e = m.m_source;
|
panic("IPC: sef_receive_status failed: %d", r);
|
||||||
call_type = m.m_type;
|
|
||||||
|
|
||||||
if(verbose)
|
if (verbose)
|
||||||
printf("IPC: get %d from %d\n", call_type, who_e);
|
printf("IPC: got %d from %d\n", m.m_type, m.m_source);
|
||||||
|
|
||||||
if (call_type & NOTIFY_MESSAGE) {
|
if (is_ipc_notify(ipc_status)) {
|
||||||
switch (who_e) {
|
switch (m.m_source) {
|
||||||
case VM_PROC_NR:
|
case VM_PROC_NR:
|
||||||
/* currently, only semaphore needs such information. */
|
/*
|
||||||
|
* Currently, only semaphore handling needs
|
||||||
|
* to know about processes exiting.
|
||||||
|
*/
|
||||||
sem_process_vm_notify();
|
sem_process_vm_notify();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("IPC: ignoring notify() from %d\n",
|
printf("IPC: ignoring notification from %d\n",
|
||||||
who_e);
|
m.m_source);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ipc_number = (unsigned int)(call_type - IPC_BASE);
|
/* Dispatch the request. */
|
||||||
|
call_index = (unsigned int)(m.m_type - IPC_BASE);
|
||||||
/* dispatch message */
|
|
||||||
if (ipc_number < __arraycount(call_vec) &&
|
|
||||||
call_vec[ipc_number] != NULL) {
|
|
||||||
/* If any process does an IPC call,
|
|
||||||
* we have to know about it exiting.
|
|
||||||
* Tell VM to watch it for us.
|
|
||||||
*/
|
|
||||||
if(vm_watch_exit(m.m_source) != OK) {
|
|
||||||
printf("IPC: watch failed on %d\n", m.m_source);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = call_vec[ipc_number](&m);
|
|
||||||
|
|
||||||
|
if (call_index < __arraycount(call_vec) &&
|
||||||
|
call_vec[call_index] != NULL) {
|
||||||
/*
|
/*
|
||||||
* The handler of the IPC call did not
|
* If any process does an IPC call, we have to know
|
||||||
* post a reply.
|
* about it exiting. Tell VM to watch it for us.
|
||||||
|
* TODO: this is not true; limit to affected processes.
|
||||||
*/
|
*/
|
||||||
if (r != SUSPEND) {
|
if (vm_watch_exit(m.m_source) != OK) {
|
||||||
m.m_type = r;
|
printf("IPC: watch failed on %d\n",
|
||||||
|
m.m_source);
|
||||||
if(verbose && r != OK)
|
|
||||||
printf("IPC: error for %d: %d\n",
|
|
||||||
call_type, r);
|
|
||||||
|
|
||||||
if ((r = ipc_sendnb(who_e, &m)) != OK)
|
|
||||||
printf("IPC send error %d.\n", r);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* warn and then ignore */
|
r = call_vec[call_index](&m);
|
||||||
printf("IPC unknown call type: %d from %d.\n",
|
} else
|
||||||
call_type, who_e);
|
r = ENOSYS;
|
||||||
|
|
||||||
|
/* Send a reply, if needed. */
|
||||||
|
if (r != SUSPEND) {
|
||||||
|
if (verbose)
|
||||||
|
printf("IPC: call result %d\n", r);
|
||||||
|
|
||||||
|
m.m_type = r;
|
||||||
|
/*
|
||||||
|
* Other fields may have been set by the handler
|
||||||
|
* function already.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((r = ipc_sendnb(m.m_source, &m)) != OK)
|
||||||
|
printf("IPC: send error %d\n", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX there must be a better way to do this! */
|
||||||
update_refcount_and_destroy();
|
update_refcount_and_destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no way to get here */
|
/* NOTREACHED */
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* sef_local_startup *
|
|
||||||
*===========================================================================*/
|
|
||||||
static void sef_local_startup(void)
|
|
||||||
{
|
|
||||||
/* Register init callbacks. */
|
|
||||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
|
||||||
sef_setcb_init_restart(sef_cb_init_fresh);
|
|
||||||
|
|
||||||
/* Register signal callbacks. */
|
|
||||||
sef_setcb_signal_handler(sef_cb_signal_handler);
|
|
||||||
|
|
||||||
/* Let SEF perform startup. */
|
|
||||||
sef_startup();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* sef_cb_init_fresh *
|
|
||||||
*===========================================================================*/
|
|
||||||
static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
|
||||||
{
|
|
||||||
/* Initialize the ipc server. */
|
|
||||||
|
|
||||||
if(verbose)
|
|
||||||
printf("IPC: self: %d\n", sef_self());
|
|
||||||
|
|
||||||
return(OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* sef_cb_signal_handler *
|
|
||||||
*===========================================================================*/
|
|
||||||
static void sef_cb_signal_handler(int signo)
|
|
||||||
{
|
|
||||||
/* Only check for termination signal, ignore anything else. */
|
|
||||||
if (signo != SIGTERM) return;
|
|
||||||
|
|
||||||
/* Checkout if there are still IPC keys. Inform the user in that case. */
|
|
||||||
if (is_sem_nil() && is_shm_nil())
|
|
||||||
sef_exit(0);
|
|
||||||
|
|
||||||
printf("IPC: exit with un-clean states.\n");
|
|
||||||
}
|
}
|
||||||
|
@ -22,22 +22,26 @@ struct sem_struct {
|
|||||||
static struct sem_struct sem_list[SEMMNI];
|
static struct sem_struct sem_list[SEMMNI];
|
||||||
static unsigned int sem_list_nr = 0; /* highest in-use slot number plus one */
|
static unsigned int sem_list_nr = 0; /* highest in-use slot number plus one */
|
||||||
|
|
||||||
static struct sem_struct *sem_find_key(key_t key)
|
static struct sem_struct *
|
||||||
|
sem_find_key(key_t key)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (key == IPC_PRIVATE)
|
if (key == IPC_PRIVATE)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (i = 0; i < sem_list_nr; i++) {
|
for (i = 0; i < sem_list_nr; i++) {
|
||||||
if (!(sem_list[i].semid_ds.sem_perm.mode & SEM_ALLOC))
|
if (!(sem_list[i].semid_ds.sem_perm.mode & SEM_ALLOC))
|
||||||
continue;
|
continue;
|
||||||
if (sem_list[i].semid_ds.sem_perm._key == key)
|
if (sem_list[i].semid_ds.sem_perm._key == key)
|
||||||
return &sem_list[i];
|
return &sem_list[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sem_struct *sem_find_id(int id)
|
static struct sem_struct *
|
||||||
|
sem_find_id(int id)
|
||||||
{
|
{
|
||||||
struct sem_struct *sem;
|
struct sem_struct *sem;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -54,10 +58,8 @@ static struct sem_struct *sem_find_id(int id)
|
|||||||
return sem;
|
return sem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
int
|
||||||
* do_semget *
|
do_semget(message * m)
|
||||||
*===========================================================================*/
|
|
||||||
int do_semget(message *m)
|
|
||||||
{
|
{
|
||||||
struct sem_struct *sem;
|
struct sem_struct *sem;
|
||||||
unsigned int i, seq;
|
unsigned int i, seq;
|
||||||
@ -68,10 +70,10 @@ int do_semget(message *m)
|
|||||||
nsems = m->m_lc_ipc_semget.nr;
|
nsems = m->m_lc_ipc_semget.nr;
|
||||||
flag = m->m_lc_ipc_semget.flag;
|
flag = m->m_lc_ipc_semget.flag;
|
||||||
|
|
||||||
if ((sem = sem_find_key(key))) {
|
if ((sem = sem_find_key(key)) != NULL) {
|
||||||
if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
|
if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
|
||||||
return EEXIST;
|
return EEXIST;
|
||||||
if (!check_perm(&sem->semid_ds.sem_perm, who_e, flag))
|
if (!check_perm(&sem->semid_ds.sem_perm, m->m_source, flag))
|
||||||
return EACCES;
|
return EACCES;
|
||||||
if (nsems > sem->semid_ds.sem_nsems)
|
if (nsems > sem->semid_ds.sem_nsems)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -92,12 +94,12 @@ int do_semget(message *m)
|
|||||||
/* Initialize the entry. */
|
/* Initialize the entry. */
|
||||||
sem = &sem_list[i];
|
sem = &sem_list[i];
|
||||||
seq = sem->semid_ds.sem_perm._seq;
|
seq = sem->semid_ds.sem_perm._seq;
|
||||||
memset(sem, 0, sizeof(struct sem_struct));
|
memset(sem, 0, sizeof(*sem));
|
||||||
sem->semid_ds.sem_perm._key = key;
|
sem->semid_ds.sem_perm._key = key;
|
||||||
sem->semid_ds.sem_perm.cuid =
|
sem->semid_ds.sem_perm.cuid =
|
||||||
sem->semid_ds.sem_perm.uid = getnuid(who_e);
|
sem->semid_ds.sem_perm.uid = getnuid(m->m_source);
|
||||||
sem->semid_ds.sem_perm.cgid =
|
sem->semid_ds.sem_perm.cgid =
|
||||||
sem->semid_ds.sem_perm.gid = getngid(who_e);
|
sem->semid_ds.sem_perm.gid = getngid(m->m_source);
|
||||||
sem->semid_ds.sem_perm.mode = SEM_ALLOC | (flag & ACCESSPERMS);
|
sem->semid_ds.sem_perm.mode = SEM_ALLOC | (flag & ACCESSPERMS);
|
||||||
sem->semid_ds.sem_perm._seq = (seq + 1) & 0x7fff;
|
sem->semid_ds.sem_perm._seq = (seq + 1) & 0x7fff;
|
||||||
sem->semid_ds.sem_nsems = nsems;
|
sem->semid_ds.sem_nsems = nsems;
|
||||||
@ -113,25 +115,42 @@ int do_semget(message *m)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_message_to_process(endpoint_t who, int ret, int ignore)
|
static void
|
||||||
|
send_reply(endpoint_t who, int ret)
|
||||||
{
|
{
|
||||||
message m;
|
message m;
|
||||||
|
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
m.m_type = ret;
|
m.m_type = ret;
|
||||||
|
|
||||||
ipc_sendnb(who, &m);
|
ipc_sendnb(who, &m);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_semaphore(struct sem_struct *sem)
|
static void
|
||||||
|
remove_semaphore(struct sem_struct * sem)
|
||||||
{
|
{
|
||||||
int i, nr;
|
int i, j, nr;
|
||||||
|
struct semaphore *semaphore;
|
||||||
|
|
||||||
nr = sem->semid_ds.sem_nsems;
|
nr = sem->semid_ds.sem_nsems;
|
||||||
|
|
||||||
|
/* Deal with processes waiting for this semaphore set. */
|
||||||
for (i = 0; i < nr; i++) {
|
for (i = 0; i < nr; i++) {
|
||||||
if (sem->sems[i].zlist)
|
semaphore = &sem->sems[i];
|
||||||
free(sem->sems[i].zlist);
|
|
||||||
if (sem->sems[i].nlist)
|
for (j = 0; j < semaphore->semzcnt; j++)
|
||||||
free(sem->sems[i].nlist);
|
send_reply(semaphore->zlist[j].who, EIDRM);
|
||||||
|
for (j = 0; j < semaphore->semncnt; j++)
|
||||||
|
send_reply(semaphore->nlist[j].who, EIDRM);
|
||||||
|
|
||||||
|
if (semaphore->zlist != NULL) {
|
||||||
|
free(semaphore->zlist);
|
||||||
|
semaphore->zlist = NULL;
|
||||||
|
}
|
||||||
|
if (semaphore->nlist != NULL) {
|
||||||
|
free(semaphore->nlist);
|
||||||
|
semaphore->nlist = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark the entry as free. */
|
/* Mark the entry as free. */
|
||||||
@ -147,7 +166,8 @@ static void remove_semaphore(struct sem_struct *sem)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void show_semaphore(void)
|
static void
|
||||||
|
show_semaphore(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int j, k, nr;
|
int j, k, nr;
|
||||||
@ -176,7 +196,8 @@ static void show_semaphore(void)
|
|||||||
printf("incr(");
|
printf("incr(");
|
||||||
for (k = 0; k < semaphore->semncnt; k++)
|
for (k = 0; k < semaphore->semncnt; k++)
|
||||||
printf("%d-%d,",
|
printf("%d-%d,",
|
||||||
semaphore->nlist[k].who, semaphore->nlist[k].val);
|
semaphore->nlist[k].who,
|
||||||
|
semaphore->nlist[k].val);
|
||||||
printf(")");
|
printf(")");
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@ -186,11 +207,14 @@ static void show_semaphore(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void remove_process(endpoint_t pt)
|
static void
|
||||||
|
remove_process(endpoint_t endpt)
|
||||||
{
|
{
|
||||||
struct sem_struct *sem;
|
struct sem_struct *sem;
|
||||||
|
struct semaphore *semaphore;
|
||||||
|
endpoint_t who_waiting;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int j, nr;
|
int j, k, nr;
|
||||||
|
|
||||||
for (i = 0; i < sem_list_nr; i++) {
|
for (i = 0; i < sem_list_nr; i++) {
|
||||||
sem = &sem_list[i];
|
sem = &sem_list[i];
|
||||||
@ -199,34 +223,39 @@ static void remove_process(endpoint_t pt)
|
|||||||
|
|
||||||
nr = sem->semid_ds.sem_nsems;
|
nr = sem->semid_ds.sem_nsems;
|
||||||
for (j = 0; j < nr; j++) {
|
for (j = 0; j < nr; j++) {
|
||||||
struct semaphore *semaphore = &sem->sems[j];
|
semaphore = &sem->sems[j];
|
||||||
int k;
|
|
||||||
|
|
||||||
for (k = 0; k < semaphore->semzcnt; k++) {
|
for (k = 0; k < semaphore->semzcnt; k++) {
|
||||||
endpoint_t who_waiting = semaphore->zlist[k].who;
|
who_waiting = semaphore->zlist[k].who;
|
||||||
|
|
||||||
if (who_waiting == pt) {
|
if (who_waiting == endpt) {
|
||||||
/* remove this slot first */
|
/* Remove this slot first. */
|
||||||
memmove(semaphore->zlist+k, semaphore->zlist+k+1,
|
memmove(semaphore->zlist + k,
|
||||||
sizeof(struct waiting) * (semaphore->semzcnt-k-1));
|
semaphore->zlist + k + 1,
|
||||||
--semaphore->semzcnt;
|
sizeof(struct waiting) *
|
||||||
/* then send message to the process */
|
(semaphore->semzcnt - k - 1));
|
||||||
send_message_to_process(who_waiting, EINTR, 1);
|
semaphore->semzcnt--;
|
||||||
|
|
||||||
|
/* Then send message to the process. */
|
||||||
|
send_reply(who_waiting, EINTR);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (k = 0; k < semaphore->semncnt; k++) {
|
for (k = 0; k < semaphore->semncnt; k++) {
|
||||||
endpoint_t who_waiting = semaphore->nlist[k].who;
|
who_waiting = semaphore->nlist[k].who;
|
||||||
|
|
||||||
if (who_waiting == pt) {
|
if (who_waiting == endpt) {
|
||||||
/* remove it first */
|
/* Remove it first. */
|
||||||
memmove(semaphore->nlist+k, semaphore->nlist+k+1,
|
memmove(semaphore->nlist + k,
|
||||||
sizeof(struct waiting) * (semaphore->semncnt-k-1));
|
semaphore->nlist + k + 1,
|
||||||
--semaphore->semncnt;
|
sizeof(struct waiting) *
|
||||||
/* send the message to the process */
|
(semaphore->semncnt-k-1));
|
||||||
send_message_to_process(who_waiting, EINTR, 1);
|
semaphore->semncnt--;
|
||||||
|
|
||||||
|
/* Send the message to the process. */
|
||||||
|
send_reply(who_waiting, EINTR);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -235,7 +264,8 @@ static void remove_process(endpoint_t pt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_one_semaphore(struct sem_struct *sem, int is_remove)
|
static void
|
||||||
|
check_semaphore(struct sem_struct * sem)
|
||||||
{
|
{
|
||||||
int i, j, nr;
|
int i, j, nr;
|
||||||
struct semaphore *semaphore;
|
struct semaphore *semaphore;
|
||||||
@ -243,47 +273,35 @@ static void update_one_semaphore(struct sem_struct *sem, int is_remove)
|
|||||||
|
|
||||||
nr = sem->semid_ds.sem_nsems;
|
nr = sem->semid_ds.sem_nsems;
|
||||||
|
|
||||||
if (is_remove) {
|
|
||||||
for (i = 0; i < nr; i++) {
|
|
||||||
semaphore = &sem->sems[i];
|
|
||||||
|
|
||||||
for (j = 0; j < semaphore->semzcnt; j++)
|
|
||||||
send_message_to_process(semaphore->zlist[j].who, EIDRM, 0);
|
|
||||||
for (j = 0; j < semaphore->semncnt; j++)
|
|
||||||
send_message_to_process(semaphore->nlist[j].who, EIDRM, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_semaphore(sem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nr; i++) {
|
for (i = 0; i < nr; i++) {
|
||||||
semaphore = &sem->sems[i];
|
semaphore = &sem->sems[i];
|
||||||
|
|
||||||
if (semaphore->zlist && !semaphore->semval) {
|
if (semaphore->zlist && !semaphore->semval) {
|
||||||
/* choose one process, policy: FIFO. */
|
/* Choose one process, policy: FIFO. */
|
||||||
who = semaphore->zlist[0].who;
|
who = semaphore->zlist[0].who;
|
||||||
|
|
||||||
memmove(semaphore->zlist, semaphore->zlist+1,
|
memmove(semaphore->zlist, semaphore->zlist + 1,
|
||||||
sizeof(struct waiting) * (semaphore->semzcnt-1));
|
sizeof(struct waiting) * (semaphore->semzcnt - 1));
|
||||||
--semaphore->semzcnt;
|
semaphore->semzcnt--;
|
||||||
|
|
||||||
send_message_to_process(who, OK, 0);
|
send_reply(who, OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (semaphore->nlist) {
|
if (semaphore->nlist) {
|
||||||
for (j = 0; j < semaphore->semncnt; j++) {
|
for (j = 0; j < semaphore->semncnt; j++) {
|
||||||
if (semaphore->nlist[j].val <= semaphore->semval) {
|
if (semaphore->nlist[j].val <=
|
||||||
semaphore->semval -= semaphore->nlist[j].val;
|
semaphore->semval) {
|
||||||
|
semaphore->semval -=
|
||||||
|
semaphore->nlist[j].val;
|
||||||
who = semaphore->nlist[j].who;
|
who = semaphore->nlist[j].who;
|
||||||
|
|
||||||
memmove(semaphore->nlist+j, semaphore->nlist+j+1,
|
memmove(semaphore->nlist + j,
|
||||||
sizeof(struct waiting) * (semaphore->semncnt-j-1));
|
semaphore->nlist + j + 1,
|
||||||
--semaphore->semncnt;
|
sizeof(struct waiting) *
|
||||||
|
(semaphore->semncnt-j-1));
|
||||||
|
semaphore->semncnt--;
|
||||||
|
|
||||||
send_message_to_process(who, OK, 0);
|
send_reply(who, OK);
|
||||||
|
|
||||||
/* choose only one process */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -291,28 +309,15 @@ static void update_one_semaphore(struct sem_struct *sem, int is_remove)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_semaphores(void)
|
int
|
||||||
{
|
do_semctl(message * m)
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i = 0; i < sem_list_nr; i++) {
|
|
||||||
if (!(sem_list[i].semid_ds.sem_perm.mode & SEM_ALLOC))
|
|
||||||
continue;
|
|
||||||
update_one_semaphore(&sem_list[i], FALSE /*is_remove*/);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*===========================================================================*
|
|
||||||
* do_semctl *
|
|
||||||
*===========================================================================*/
|
|
||||||
int do_semctl(message *m)
|
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
vir_bytes opt;
|
vir_bytes opt;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
int r, id, num, cmd, val;
|
int r, id, num, cmd, val;
|
||||||
unsigned short *buf;
|
unsigned short *buf;
|
||||||
struct semid_ds *ds, tmp_ds;
|
struct semid_ds tmp_ds;
|
||||||
struct sem_struct *sem;
|
struct sem_struct *sem;
|
||||||
struct seminfo sinfo;
|
struct seminfo sinfo;
|
||||||
|
|
||||||
@ -334,37 +339,38 @@ int do_semctl(message *m)
|
|||||||
return EINVAL;
|
return EINVAL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!(sem = sem_find_id(id)))
|
if ((sem = sem_find_id(id)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IPC_SET and IPC_RMID as its own permission check */
|
/*
|
||||||
|
* IPC_SET and IPC_RMID have their own permission checks. IPC_INFO and
|
||||||
|
* SEM_INFO are free for general use.
|
||||||
|
*/
|
||||||
if (sem != NULL && cmd != IPC_SET && cmd != IPC_RMID) {
|
if (sem != NULL && cmd != IPC_SET && cmd != IPC_RMID) {
|
||||||
/* check read permission */
|
/* Check read permission. */
|
||||||
if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0444))
|
if (!check_perm(&sem->semid_ds.sem_perm, m->m_source, 0444))
|
||||||
return EACCES;
|
return EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case IPC_STAT:
|
case IPC_STAT:
|
||||||
case SEM_STAT:
|
case SEM_STAT:
|
||||||
if ((r = sys_datacopy(SELF, (vir_bytes)&sem->semid_ds, who_e,
|
if ((r = sys_datacopy(SELF, (vir_bytes)&sem->semid_ds,
|
||||||
(vir_bytes)opt, sizeof(sem->semid_ds))) != OK)
|
m->m_source, opt, sizeof(sem->semid_ds))) != OK)
|
||||||
return r;
|
return r;
|
||||||
if (cmd == SEM_STAT)
|
if (cmd == SEM_STAT)
|
||||||
m->m_lc_ipc_semctl.ret =
|
m->m_lc_ipc_semctl.ret =
|
||||||
IXSEQ_TO_IPCID(id, sem->semid_ds.sem_perm);
|
IXSEQ_TO_IPCID(id, sem->semid_ds.sem_perm);
|
||||||
break;
|
break;
|
||||||
case IPC_SET:
|
case IPC_SET:
|
||||||
uid = getnuid(who_e);
|
uid = getnuid(m->m_source);
|
||||||
if (uid != sem->semid_ds.sem_perm.cuid &&
|
if (uid != sem->semid_ds.sem_perm.cuid &&
|
||||||
uid != sem->semid_ds.sem_perm.uid &&
|
uid != sem->semid_ds.sem_perm.uid && uid != 0)
|
||||||
uid != 0)
|
|
||||||
return EPERM;
|
return EPERM;
|
||||||
ds = (struct semid_ds *) opt;
|
if ((r = sys_datacopy(m->m_source, opt, SELF,
|
||||||
if ((r = sys_datacopy(who_e, (vir_bytes)ds, SELF,
|
(vir_bytes)&tmp_ds, sizeof(tmp_ds))) != OK)
|
||||||
(vir_bytes)&tmp_ds, sizeof(struct semid_ds))) != OK)
|
|
||||||
return r;
|
return r;
|
||||||
sem->semid_ds.sem_perm.uid = tmp_ds.sem_perm.uid;
|
sem->semid_ds.sem_perm.uid = tmp_ds.sem_perm.uid;
|
||||||
sem->semid_ds.sem_perm.gid = tmp_ds.sem_perm.gid;
|
sem->semid_ds.sem_perm.gid = tmp_ds.sem_perm.gid;
|
||||||
@ -374,15 +380,15 @@ int do_semctl(message *m)
|
|||||||
sem->semid_ds.sem_ctime = clock_time(NULL);
|
sem->semid_ds.sem_ctime = clock_time(NULL);
|
||||||
break;
|
break;
|
||||||
case IPC_RMID:
|
case IPC_RMID:
|
||||||
uid = getnuid(who_e);
|
uid = getnuid(m->m_source);
|
||||||
if (uid != sem->semid_ds.sem_perm.cuid &&
|
if (uid != sem->semid_ds.sem_perm.cuid &&
|
||||||
uid != sem->semid_ds.sem_perm.uid &&
|
uid != sem->semid_ds.sem_perm.uid && uid != 0)
|
||||||
uid != 0)
|
|
||||||
return EPERM;
|
return EPERM;
|
||||||
/* awaken all processes block in semop
|
/*
|
||||||
* and remove the semaphore set.
|
* Awaken all processes blocked in semop(2) on any semaphore in
|
||||||
|
* this set, and remove the semaphore set itself.
|
||||||
*/
|
*/
|
||||||
update_one_semaphore(sem, TRUE /*is_remove*/);
|
remove_semaphore(sem);
|
||||||
break;
|
break;
|
||||||
case IPC_INFO:
|
case IPC_INFO:
|
||||||
case SEM_INFO:
|
case SEM_INFO:
|
||||||
@ -413,8 +419,8 @@ int do_semctl(message *m)
|
|||||||
} else
|
} else
|
||||||
sinfo.semaem = 0; /* TODO: support for SEM_UNDO */
|
sinfo.semaem = 0; /* TODO: support for SEM_UNDO */
|
||||||
|
|
||||||
if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, who_e,
|
if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, m->m_source,
|
||||||
(vir_bytes)opt, sizeof(sinfo))) != OK)
|
opt, sizeof(sinfo))) != OK)
|
||||||
return r;
|
return r;
|
||||||
/* Return the highest in-use slot number if any, or zero. */
|
/* Return the highest in-use slot number if any, or zero. */
|
||||||
if (sem_list_nr > 0)
|
if (sem_list_nr > 0)
|
||||||
@ -428,8 +434,8 @@ int do_semctl(message *m)
|
|||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
for (i = 0; i < sem->semid_ds.sem_nsems; i++)
|
for (i = 0; i < sem->semid_ds.sem_nsems; i++)
|
||||||
buf[i] = sem->sems[i].semval;
|
buf[i] = sem->sems[i].semval;
|
||||||
r = sys_datacopy(SELF, (vir_bytes)buf, who_e, (vir_bytes)opt,
|
r = sys_datacopy(SELF, (vir_bytes)buf, m->m_source,
|
||||||
sizeof(unsigned short) * sem->semid_ds.sem_nsems);
|
opt, sizeof(unsigned short) * sem->semid_ds.sem_nsems);
|
||||||
free(buf);
|
free(buf);
|
||||||
if (r != OK)
|
if (r != OK)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -458,33 +464,32 @@ int do_semctl(message *m)
|
|||||||
buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);
|
buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
r = sys_datacopy(who_e, (vir_bytes)opt, SELF, (vir_bytes)buf,
|
r = sys_datacopy(m->m_source, opt, SELF, (vir_bytes)buf,
|
||||||
sizeof(unsigned short) * sem->semid_ds.sem_nsems);
|
sizeof(unsigned short) * sem->semid_ds.sem_nsems);
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
free(buf);
|
free(buf);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_SEM
|
|
||||||
printf("SEMCTL: SETALL: opt: %lu\n", (vir_bytes) opt);
|
|
||||||
for (i = 0; i < sem->semid_ds.sem_nsems; i++)
|
|
||||||
printf("SEMCTL: SETALL val: [%d] %d\n", i, buf[i]);
|
|
||||||
#endif
|
|
||||||
for (i = 0; i < sem->semid_ds.sem_nsems; i++) {
|
for (i = 0; i < sem->semid_ds.sem_nsems; i++) {
|
||||||
if (buf[i] > SEMVMX) {
|
if (buf[i] > SEMVMX) {
|
||||||
free(buf);
|
free(buf);
|
||||||
update_semaphores();
|
|
||||||
return ERANGE;
|
return ERANGE;
|
||||||
}
|
}
|
||||||
sem->sems[i].semval = buf[i];
|
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG_SEM
|
||||||
|
for (i = 0; i < sem->semid_ds.sem_nsems; i++)
|
||||||
|
printf("SEMCTL: SETALL val: [%d] %d\n", i, buf[i]);
|
||||||
|
#endif
|
||||||
|
for (i = 0; i < sem->semid_ds.sem_nsems; i++)
|
||||||
|
sem->sems[i].semval = buf[i];
|
||||||
free(buf);
|
free(buf);
|
||||||
/* awaken if possible */
|
/* Awaken any waiting parties if now possible. */
|
||||||
update_semaphores();
|
check_semaphore(sem);
|
||||||
break;
|
break;
|
||||||
case SETVAL:
|
case SETVAL:
|
||||||
val = (int) opt;
|
val = (int)opt;
|
||||||
/* check write permission */
|
/* Check write permission. */
|
||||||
if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222))
|
if (!check_perm(&sem->semid_ds.sem_perm, m->m_source, 0222))
|
||||||
return EACCES;
|
return EACCES;
|
||||||
if (num < 0 || num >= sem->semid_ds.sem_nsems)
|
if (num < 0 || num >= sem->semid_ds.sem_nsems)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -495,8 +500,8 @@ int do_semctl(message *m)
|
|||||||
printf("SEMCTL: SETVAL: %d %d\n", num, val);
|
printf("SEMCTL: SETVAL: %d %d\n", num, val);
|
||||||
#endif
|
#endif
|
||||||
sem->semid_ds.sem_ctime = clock_time(NULL);
|
sem->semid_ds.sem_ctime = clock_time(NULL);
|
||||||
/* awaken if possible */
|
/* Awaken any waiting parties if now possible. */
|
||||||
update_semaphores();
|
check_semaphore(sem);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -505,22 +510,21 @@ int do_semctl(message *m)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
int
|
||||||
* do_semop *
|
do_semop(message * m)
|
||||||
*===========================================================================*/
|
|
||||||
int do_semop(message *m)
|
|
||||||
{
|
{
|
||||||
unsigned int i, j, mask;
|
unsigned int i, mask;
|
||||||
int id, r;
|
int id, r;
|
||||||
struct sembuf *sops;
|
struct sembuf *sops;
|
||||||
unsigned int nsops;
|
unsigned int nsops;
|
||||||
struct sem_struct *sem;
|
struct sem_struct *sem;
|
||||||
int no_reply = 0;
|
struct semaphore *s;
|
||||||
|
int op_n, val, no_reply;
|
||||||
|
|
||||||
id = m->m_lc_ipc_semop.id;
|
id = m->m_lc_ipc_semop.id;
|
||||||
nsops = m->m_lc_ipc_semop.size;
|
nsops = m->m_lc_ipc_semop.size;
|
||||||
|
|
||||||
if (!(sem = sem_find_id(id)))
|
if ((sem = sem_find_id(id)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if (nsops <= 0)
|
if (nsops <= 0)
|
||||||
@ -528,13 +532,12 @@ int do_semop(message *m)
|
|||||||
if (nsops > SEMOPM)
|
if (nsops > SEMOPM)
|
||||||
return E2BIG;
|
return E2BIG;
|
||||||
|
|
||||||
/* get the array from user application */
|
/* Get the array from the user process. */
|
||||||
sops = malloc(sizeof(struct sembuf) * nsops);
|
sops = malloc(sizeof(sops[0]) * nsops);
|
||||||
if (!sops)
|
if (!sops)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
r = sys_datacopy(who_e, (vir_bytes) m->m_lc_ipc_semop.ops,
|
r = sys_datacopy(m->m_source, (vir_bytes)m->m_lc_ipc_semop.ops, SELF,
|
||||||
SELF, (vir_bytes) sops,
|
(vir_bytes)sops, sizeof(sops[0]) * nsops);
|
||||||
sizeof(struct sembuf) * nsops);
|
|
||||||
if (r != OK)
|
if (r != OK)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
@ -543,13 +546,13 @@ int do_semop(message *m)
|
|||||||
printf("SEMOP: num:%d op:%d flg:%d\n",
|
printf("SEMOP: num:%d op:%d flg:%d\n",
|
||||||
sops[i].sem_num, sops[i].sem_op, sops[i].sem_flg);
|
sops[i].sem_num, sops[i].sem_op, sops[i].sem_flg);
|
||||||
#endif
|
#endif
|
||||||
/* check for value range */
|
/* Check that all given semaphore numbers are within range. */
|
||||||
r = EFBIG;
|
r = EFBIG;
|
||||||
for (i = 0; i < nsops; i++)
|
for (i = 0; i < nsops; i++)
|
||||||
if (sops[i].sem_num >= sem->semid_ds.sem_nsems)
|
if (sops[i].sem_num >= sem->semid_ds.sem_nsems)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
/* check for permissions */
|
/* Check for permissions. */
|
||||||
r = EACCES;
|
r = EACCES;
|
||||||
mask = 0;
|
mask = 0;
|
||||||
for (i = 0; i < nsops; i++) {
|
for (i = 0; i < nsops; i++) {
|
||||||
@ -558,73 +561,58 @@ int do_semop(message *m)
|
|||||||
else
|
else
|
||||||
mask |= 0444; /* check for read permission */
|
mask |= 0444; /* check for read permission */
|
||||||
}
|
}
|
||||||
if (mask && !check_perm(&sem->semid_ds.sem_perm, who_e, mask))
|
if (mask && !check_perm(&sem->semid_ds.sem_perm, m->m_source, mask))
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
/* check for duplicate number */
|
/* Check for nonblocking operations. */
|
||||||
r = EINVAL;
|
|
||||||
for (i = 0; i < nsops; i++)
|
|
||||||
for (j = i + 1; j < nsops; j++)
|
|
||||||
if (sops[i].sem_num == sops[j].sem_num)
|
|
||||||
goto out_free;
|
|
||||||
|
|
||||||
/* check for nonblocking operations */
|
|
||||||
r = EAGAIN;
|
r = EAGAIN;
|
||||||
for (i = 0; i < nsops; i++) {
|
for (i = 0; i < nsops; i++) {
|
||||||
int op_n, val;
|
|
||||||
|
|
||||||
op_n = sops[i].sem_op;
|
op_n = sops[i].sem_op;
|
||||||
val = sem->sems[sops[i].sem_num].semval;
|
val = sem->sems[sops[i].sem_num].semval;
|
||||||
|
|
||||||
if ((sops[i].sem_flg & IPC_NOWAIT) &&
|
if ((sops[i].sem_flg & IPC_NOWAIT) &&
|
||||||
((!op_n && val) ||
|
((op_n == 0 && val != 0) || (op_n < 0 && -op_n > val)))
|
||||||
(op_n < 0 &&
|
|
||||||
-op_n > val)))
|
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* there will be no errors left, so we can go ahead */
|
/* There will be no errors left, so we can go ahead. */
|
||||||
|
no_reply = 0;
|
||||||
for (i = 0; i < nsops; i++) {
|
for (i = 0; i < nsops; i++) {
|
||||||
struct semaphore *s;
|
|
||||||
int op_n;
|
|
||||||
|
|
||||||
s = &sem->sems[sops[i].sem_num];
|
s = &sem->sems[sops[i].sem_num];
|
||||||
op_n = sops[i].sem_op;
|
op_n = sops[i].sem_op;
|
||||||
|
|
||||||
s->sempid = getnpid(who_e);
|
s->sempid = getnpid(m->m_source);
|
||||||
|
|
||||||
if (op_n > 0) {
|
if (op_n > 0) {
|
||||||
|
/* XXX missing ERANGE check */
|
||||||
s->semval += sops[i].sem_op;
|
s->semval += sops[i].sem_op;
|
||||||
} else if (!op_n) {
|
} else if (op_n == 0) {
|
||||||
if (s->semval) {
|
if (s->semval) {
|
||||||
/* put the process asleep */
|
/* Put the process to sleep. */
|
||||||
s->semzcnt++;
|
s->semzcnt++;
|
||||||
s->zlist = realloc(s->zlist,
|
s->zlist = realloc(s->zlist,
|
||||||
sizeof(struct waiting) * s->semzcnt);
|
sizeof(struct waiting) * s->semzcnt);
|
||||||
/* continuing if NULL would lead to disaster */
|
/* continuing if NULL would lead to disaster */
|
||||||
if (s->zlist == NULL)
|
if (s->zlist == NULL)
|
||||||
panic("out of memory");
|
panic("out of memory");
|
||||||
s->zlist[s->semzcnt-1].who = who_e;
|
s->zlist[s->semzcnt - 1].who = m->m_source;
|
||||||
s->zlist[s->semzcnt-1].val = op_n;
|
s->zlist[s->semzcnt - 1].val = op_n;
|
||||||
|
|
||||||
#ifdef DEBUG_SEM
|
|
||||||
printf("SEMOP: Put into sleep... %d\n", who_e);
|
|
||||||
#endif
|
|
||||||
no_reply++;
|
no_reply++;
|
||||||
}
|
}
|
||||||
} else {
|
} else /* (op_n < 0) */ {
|
||||||
if (s->semval >= -op_n)
|
if (s->semval >= -op_n)
|
||||||
s->semval += op_n;
|
s->semval += op_n;
|
||||||
else {
|
else {
|
||||||
/* put the process asleep */
|
/* Put the process to sleep. */
|
||||||
s->semncnt++;
|
s->semncnt++;
|
||||||
s->nlist = realloc(s->nlist,
|
s->nlist = realloc(s->nlist,
|
||||||
sizeof(struct waiting) * s->semncnt);
|
sizeof(struct waiting) * s->semncnt);
|
||||||
/* continuing if NULL would lead to disaster */
|
/* continuing if NULL would lead to disaster */
|
||||||
if (s->nlist == NULL)
|
if (s->nlist == NULL)
|
||||||
panic("out of memory");
|
panic("out of memory");
|
||||||
s->nlist[s->semncnt-1].who = who_e;
|
s->nlist[s->semncnt - 1].who = m->m_source;
|
||||||
s->nlist[s->semncnt-1].val = -op_n;
|
s->nlist[s->semncnt - 1].val = -op_n;
|
||||||
|
|
||||||
no_reply++;
|
no_reply++;
|
||||||
}
|
}
|
||||||
@ -632,39 +620,36 @@ int do_semop(message *m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
r = no_reply ? SUSPEND : OK;
|
r = no_reply ? SUSPEND : OK;
|
||||||
|
|
||||||
|
/* Awaken any other waiting parties if now possible. */
|
||||||
|
check_semaphore(sem);
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
free(sops);
|
free(sops);
|
||||||
|
|
||||||
/* awaken process if possible */
|
|
||||||
update_semaphores();
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
int
|
||||||
* is_sem_nil *
|
is_sem_nil(void)
|
||||||
*===========================================================================*/
|
|
||||||
int is_sem_nil(void)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
return (sem_list_nr == 0);
|
return (sem_list_nr == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
void
|
||||||
* sem_process_vm_notify *
|
sem_process_vm_notify(void)
|
||||||
*===========================================================================*/
|
|
||||||
void sem_process_vm_notify(void)
|
|
||||||
{
|
{
|
||||||
endpoint_t pt;
|
endpoint_t endpt;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
while ((r = vm_query_exit(&pt)) >= 0) {
|
/* For each endpoint, check whether it is waiting. */
|
||||||
/* for each enpoint 'pt', check whether it's waiting... */
|
while ((r = vm_query_exit(&endpt)) >= 0) {
|
||||||
remove_process(pt);
|
remove_process(endpt);
|
||||||
|
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
printf("IPC: query exit error!\n");
|
printf("IPC: query exit error (%d)\n", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,22 +11,26 @@ struct shm_struct {
|
|||||||
static struct shm_struct shm_list[SHMMNI];
|
static struct shm_struct shm_list[SHMMNI];
|
||||||
static unsigned int shm_list_nr = 0; /* highest in-use slot number plus one */
|
static unsigned int shm_list_nr = 0; /* highest in-use slot number plus one */
|
||||||
|
|
||||||
static struct shm_struct *shm_find_key(key_t key)
|
static struct shm_struct *
|
||||||
|
shm_find_key(key_t key)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (key == IPC_PRIVATE)
|
if (key == IPC_PRIVATE)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (i = 0; i < shm_list_nr; i++) {
|
for (i = 0; i < shm_list_nr; i++) {
|
||||||
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
|
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
|
||||||
continue;
|
continue;
|
||||||
if (shm_list[i].shmid_ds.shm_perm._key == key)
|
if (shm_list[i].shmid_ds.shm_perm._key == key)
|
||||||
return &shm_list[i];
|
return &shm_list[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct shm_struct *shm_find_id(int id)
|
static struct shm_struct *
|
||||||
|
shm_find_id(int id)
|
||||||
{
|
{
|
||||||
struct shm_struct *shm;
|
struct shm_struct *shm;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -43,10 +47,8 @@ static struct shm_struct *shm_find_id(int id)
|
|||||||
return shm;
|
return shm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
int
|
||||||
* do_shmget *
|
do_shmget(message * m)
|
||||||
*===========================================================================*/
|
|
||||||
int do_shmget(message *m)
|
|
||||||
{
|
{
|
||||||
struct shm_struct *shm;
|
struct shm_struct *shm;
|
||||||
unsigned int i, seq;
|
unsigned int i, seq;
|
||||||
@ -59,8 +61,8 @@ int do_shmget(message *m)
|
|||||||
old_size = size = m->m_lc_ipc_shmget.size;
|
old_size = size = m->m_lc_ipc_shmget.size;
|
||||||
flag = m->m_lc_ipc_shmget.flag;
|
flag = m->m_lc_ipc_shmget.flag;
|
||||||
|
|
||||||
if ((shm = shm_find_key(key))) {
|
if ((shm = shm_find_key(key)) != NULL) {
|
||||||
if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag))
|
if (!check_perm(&shm->shmid_ds.shm_perm, m->m_source, flag))
|
||||||
return EACCES;
|
return EACCES;
|
||||||
if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
|
if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
|
||||||
return EEXIST;
|
return EEXIST;
|
||||||
@ -72,9 +74,7 @@ int do_shmget(message *m)
|
|||||||
return ENOENT;
|
return ENOENT;
|
||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
/* round up to a multiple of PAGE_SIZE */
|
size = roundup(size, PAGE_SIZE);
|
||||||
if (size % PAGE_SIZE)
|
|
||||||
size += PAGE_SIZE - size % PAGE_SIZE;
|
|
||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
@ -98,20 +98,20 @@ int do_shmget(message *m)
|
|||||||
/* Initialize the entry. */
|
/* Initialize the entry. */
|
||||||
shm = &shm_list[i];
|
shm = &shm_list[i];
|
||||||
seq = shm->shmid_ds.shm_perm._seq;
|
seq = shm->shmid_ds.shm_perm._seq;
|
||||||
memset(shm, 0, sizeof(struct shm_struct));
|
memset(shm, 0, sizeof(*shm));
|
||||||
|
|
||||||
shm->shmid_ds.shm_perm._key = key;
|
shm->shmid_ds.shm_perm._key = key;
|
||||||
shm->shmid_ds.shm_perm.cuid =
|
shm->shmid_ds.shm_perm.cuid =
|
||||||
shm->shmid_ds.shm_perm.uid = getnuid(who_e);
|
shm->shmid_ds.shm_perm.uid = getnuid(m->m_source);
|
||||||
shm->shmid_ds.shm_perm.cgid =
|
shm->shmid_ds.shm_perm.cgid =
|
||||||
shm->shmid_ds.shm_perm.gid = getngid(who_e);
|
shm->shmid_ds.shm_perm.gid = getngid(m->m_source);
|
||||||
shm->shmid_ds.shm_perm.mode = SHM_ALLOC | (flag & ACCESSPERMS);
|
shm->shmid_ds.shm_perm.mode = SHM_ALLOC | (flag & ACCESSPERMS);
|
||||||
shm->shmid_ds.shm_perm._seq = (seq + 1) & 0x7fff;
|
shm->shmid_ds.shm_perm._seq = (seq + 1) & 0x7fff;
|
||||||
shm->shmid_ds.shm_segsz = old_size;
|
shm->shmid_ds.shm_segsz = old_size;
|
||||||
shm->shmid_ds.shm_atime = 0;
|
shm->shmid_ds.shm_atime = 0;
|
||||||
shm->shmid_ds.shm_dtime = 0;
|
shm->shmid_ds.shm_dtime = 0;
|
||||||
shm->shmid_ds.shm_ctime = clock_time(NULL);
|
shm->shmid_ds.shm_ctime = clock_time(NULL);
|
||||||
shm->shmid_ds.shm_cpid = getnpid(who_e);
|
shm->shmid_ds.shm_cpid = getnpid(m->m_source);
|
||||||
shm->shmid_ds.shm_lpid = 0;
|
shm->shmid_ds.shm_lpid = 0;
|
||||||
shm->shmid_ds.shm_nattch = 0;
|
shm->shmid_ds.shm_nattch = 0;
|
||||||
shm->page = (vir_bytes)page;
|
shm->page = (vir_bytes)page;
|
||||||
@ -126,10 +126,8 @@ int do_shmget(message *m)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
int
|
||||||
* do_shmat *
|
do_shmat(message * m)
|
||||||
*===========================================================================*/
|
|
||||||
int do_shmat(message *m)
|
|
||||||
{
|
{
|
||||||
int id, flag;
|
int id, flag;
|
||||||
vir_bytes addr;
|
vir_bytes addr;
|
||||||
@ -137,45 +135,42 @@ int do_shmat(message *m)
|
|||||||
struct shm_struct *shm;
|
struct shm_struct *shm;
|
||||||
|
|
||||||
id = m->m_lc_ipc_shmat.id;
|
id = m->m_lc_ipc_shmat.id;
|
||||||
addr = (vir_bytes) m->m_lc_ipc_shmat.addr;
|
addr = (vir_bytes)m->m_lc_ipc_shmat.addr;
|
||||||
flag = m->m_lc_ipc_shmat.flag;
|
flag = m->m_lc_ipc_shmat.flag;
|
||||||
|
|
||||||
if (addr && (addr % PAGE_SIZE)) {
|
if (addr % PAGE_SIZE) {
|
||||||
if (flag & SHM_RND)
|
if (flag & SHM_RND)
|
||||||
addr -= (addr % PAGE_SIZE);
|
addr -= addr % PAGE_SIZE;
|
||||||
else
|
else
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(shm = shm_find_id(id)))
|
if ((shm = shm_find_id(id)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if (flag & SHM_RDONLY)
|
if (flag & SHM_RDONLY)
|
||||||
flag = 0444;
|
flag = 0444;
|
||||||
else
|
else
|
||||||
flag = 0666;
|
flag = 0666;
|
||||||
if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag))
|
if (!check_perm(&shm->shmid_ds.shm_perm, m->m_source, flag))
|
||||||
return EACCES;
|
return EACCES;
|
||||||
|
|
||||||
ret = vm_remap(who_e, sef_self(), (void *)addr, (void *)shm->page,
|
ret = vm_remap(m->m_source, sef_self(), (void *)addr,
|
||||||
shm->shmid_ds.shm_segsz);
|
(void *)shm->page, shm->shmid_ds.shm_segsz);
|
||||||
if (ret == MAP_FAILED)
|
if (ret == MAP_FAILED)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
shm->shmid_ds.shm_atime = clock_time(NULL);
|
shm->shmid_ds.shm_atime = clock_time(NULL);
|
||||||
shm->shmid_ds.shm_lpid = getnpid(who_e);
|
shm->shmid_ds.shm_lpid = getnpid(m->m_source);
|
||||||
/* nattach is updated lazily */
|
/* nattch is updated lazily */
|
||||||
|
|
||||||
m->m_lc_ipc_shmat.retaddr = ret;
|
m->m_lc_ipc_shmat.retaddr = ret;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
void
|
||||||
* update_refcount_and_destroy *
|
update_refcount_and_destroy(void)
|
||||||
*===========================================================================*/
|
|
||||||
void update_refcount_and_destroy(void)
|
|
||||||
{
|
{
|
||||||
size_t size;
|
|
||||||
u8_t rc;
|
u8_t rc;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -183,8 +178,8 @@ void update_refcount_and_destroy(void)
|
|||||||
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
|
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rc = vm_getrefcount(sef_self(), (void *) shm_list[i].page);
|
rc = vm_getrefcount(sef_self(), (void *)shm_list[i].page);
|
||||||
if (rc == (u8_t) -1) {
|
if (rc == (u8_t)-1) {
|
||||||
printf("IPC: can't find physical region.\n");
|
printf("IPC: can't find physical region.\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -192,10 +187,9 @@ void update_refcount_and_destroy(void)
|
|||||||
|
|
||||||
if (shm_list[i].shmid_ds.shm_nattch == 0 &&
|
if (shm_list[i].shmid_ds.shm_nattch == 0 &&
|
||||||
(shm_list[i].shmid_ds.shm_perm.mode & SHM_DEST)) {
|
(shm_list[i].shmid_ds.shm_perm.mode & SHM_DEST)) {
|
||||||
size = shm_list[i].shmid_ds.shm_segsz;
|
munmap((void *)shm_list[i].page,
|
||||||
if (size % PAGE_SIZE)
|
roundup(shm_list[i].shmid_ds.shm_segsz,
|
||||||
size += PAGE_SIZE - size % PAGE_SIZE;
|
PAGE_SIZE));
|
||||||
munmap((void *)shm_list[i].page, size);
|
|
||||||
/* Mark the entry as free. */
|
/* Mark the entry as free. */
|
||||||
shm_list[i].shmid_ds.shm_perm.mode &= ~SHM_ALLOC;
|
shm_list[i].shmid_ds.shm_perm.mode &= ~SHM_ALLOC;
|
||||||
}
|
}
|
||||||
@ -210,19 +204,17 @@ void update_refcount_and_destroy(void)
|
|||||||
shm_list_nr--;
|
shm_list_nr--;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
int
|
||||||
* do_shmdt *
|
do_shmdt(message * m)
|
||||||
*===========================================================================*/
|
|
||||||
int do_shmdt(message *m)
|
|
||||||
{
|
{
|
||||||
struct shm_struct *shm;
|
struct shm_struct *shm;
|
||||||
vir_bytes addr;
|
vir_bytes addr;
|
||||||
phys_bytes vm_id;
|
phys_bytes vm_id;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
addr = (vir_bytes) m->m_lc_ipc_shmdt.addr;
|
addr = (vir_bytes)m->m_lc_ipc_shmdt.addr;
|
||||||
|
|
||||||
if ((vm_id = vm_getphys(who_e, (void *) addr)) == 0)
|
if ((vm_id = vm_getphys(m->m_source, (void *)addr)) == 0)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < shm_list_nr; i++) {
|
for (i = 0; i < shm_list_nr; i++) {
|
||||||
@ -233,39 +225,36 @@ int do_shmdt(message *m)
|
|||||||
|
|
||||||
if (shm->vm_id == vm_id) {
|
if (shm->vm_id == vm_id) {
|
||||||
shm->shmid_ds.shm_atime = clock_time(NULL);
|
shm->shmid_ds.shm_atime = clock_time(NULL);
|
||||||
shm->shmid_ds.shm_lpid = getnpid(who_e);
|
shm->shmid_ds.shm_lpid = getnpid(m->m_source);
|
||||||
/* nattch is updated lazily */
|
/* nattch is updated lazily */
|
||||||
|
|
||||||
vm_unmap(who_e, (void *) addr);
|
vm_unmap(m->m_source, (void *)addr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i == shm_list_nr)
|
if (i == shm_list_nr)
|
||||||
printf("IPC: do_shmdt impossible error! could not find id %lu to unmap\n",
|
printf("IPC: do_shmdt: ID %lu not found\n", vm_id);
|
||||||
vm_id);
|
|
||||||
|
|
||||||
update_refcount_and_destroy();
|
update_refcount_and_destroy();
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
int
|
||||||
* do_shmctl *
|
do_shmctl(message * m)
|
||||||
*===========================================================================*/
|
|
||||||
int do_shmctl(message *m)
|
|
||||||
{
|
{
|
||||||
struct shmid_ds *ds;
|
|
||||||
struct shmid_ds tmp_ds;
|
struct shmid_ds tmp_ds;
|
||||||
struct shm_struct *shm;
|
struct shm_struct *shm;
|
||||||
struct shminfo sinfo;
|
struct shminfo sinfo;
|
||||||
struct shm_info s_info;
|
struct shm_info s_info;
|
||||||
|
vir_bytes buf;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
int r, id, cmd;
|
int r, id, cmd;
|
||||||
|
|
||||||
id = m->m_lc_ipc_shmctl.id;
|
id = m->m_lc_ipc_shmctl.id;
|
||||||
cmd = m->m_lc_ipc_shmctl.cmd;
|
cmd = m->m_lc_ipc_shmctl.cmd;
|
||||||
ds = (struct shmid_ds *)m->m_lc_ipc_shmctl.buf;
|
buf = (vir_bytes)m->m_lc_ipc_shmctl.buf;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For stat calls, sure that all information is up-to-date. Since this
|
* For stat calls, sure that all information is up-to-date. Since this
|
||||||
@ -287,7 +276,7 @@ int do_shmctl(message *m)
|
|||||||
return EINVAL;
|
return EINVAL;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!(shm = shm_find_id(id)))
|
if ((shm = shm_find_id(id)) == NULL)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -296,23 +285,22 @@ int do_shmctl(message *m)
|
|||||||
case IPC_STAT:
|
case IPC_STAT:
|
||||||
case SHM_STAT:
|
case SHM_STAT:
|
||||||
/* Check whether the caller has read permission. */
|
/* Check whether the caller has read permission. */
|
||||||
if (!check_perm(&shm->shmid_ds.shm_perm, who_e, 0444))
|
if (!check_perm(&shm->shmid_ds.shm_perm, m->m_source, 0444))
|
||||||
return EACCES;
|
return EACCES;
|
||||||
if ((r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds, who_e,
|
if ((r = sys_datacopy(SELF, (vir_bytes)&shm->shmid_ds,
|
||||||
(vir_bytes)ds, sizeof(struct shmid_ds))) != OK)
|
m->m_source, buf, sizeof(shm->shmid_ds))) != OK)
|
||||||
return r;
|
return r;
|
||||||
if (cmd == SHM_STAT)
|
if (cmd == SHM_STAT)
|
||||||
m->m_lc_ipc_shmctl.ret =
|
m->m_lc_ipc_shmctl.ret =
|
||||||
IXSEQ_TO_IPCID(id, shm->shmid_ds.shm_perm);
|
IXSEQ_TO_IPCID(id, shm->shmid_ds.shm_perm);
|
||||||
break;
|
break;
|
||||||
case IPC_SET:
|
case IPC_SET:
|
||||||
uid = getnuid(who_e);
|
uid = getnuid(m->m_source);
|
||||||
if (uid != shm->shmid_ds.shm_perm.cuid &&
|
if (uid != shm->shmid_ds.shm_perm.cuid &&
|
||||||
uid != shm->shmid_ds.shm_perm.uid &&
|
uid != shm->shmid_ds.shm_perm.uid && uid != 0)
|
||||||
uid != 0)
|
|
||||||
return EPERM;
|
return EPERM;
|
||||||
if ((r = sys_datacopy(who_e, (vir_bytes)ds, SELF,
|
if ((r = sys_datacopy(m->m_source, buf, SELF,
|
||||||
(vir_bytes)&tmp_ds, sizeof(struct shmid_ds))) != OK)
|
(vir_bytes)&tmp_ds, sizeof(tmp_ds))) != OK)
|
||||||
return r;
|
return r;
|
||||||
shm->shmid_ds.shm_perm.uid = tmp_ds.shm_perm.uid;
|
shm->shmid_ds.shm_perm.uid = tmp_ds.shm_perm.uid;
|
||||||
shm->shmid_ds.shm_perm.gid = tmp_ds.shm_perm.gid;
|
shm->shmid_ds.shm_perm.gid = tmp_ds.shm_perm.gid;
|
||||||
@ -322,13 +310,12 @@ int do_shmctl(message *m)
|
|||||||
shm->shmid_ds.shm_ctime = clock_time(NULL);
|
shm->shmid_ds.shm_ctime = clock_time(NULL);
|
||||||
break;
|
break;
|
||||||
case IPC_RMID:
|
case IPC_RMID:
|
||||||
uid = getnuid(who_e);
|
uid = getnuid(m->m_source);
|
||||||
if (uid != shm->shmid_ds.shm_perm.cuid &&
|
if (uid != shm->shmid_ds.shm_perm.cuid &&
|
||||||
uid != shm->shmid_ds.shm_perm.uid &&
|
uid != shm->shmid_ds.shm_perm.uid && uid != 0)
|
||||||
uid != 0)
|
|
||||||
return EPERM;
|
return EPERM;
|
||||||
shm->shmid_ds.shm_perm.mode |= SHM_DEST;
|
shm->shmid_ds.shm_perm.mode |= SHM_DEST;
|
||||||
/* destroy if possible */
|
/* Destroy if possible. */
|
||||||
update_refcount_and_destroy();
|
update_refcount_and_destroy();
|
||||||
break;
|
break;
|
||||||
case IPC_INFO:
|
case IPC_INFO:
|
||||||
@ -338,8 +325,8 @@ int do_shmctl(message *m)
|
|||||||
sinfo.shmmni = __arraycount(shm_list);
|
sinfo.shmmni = __arraycount(shm_list);
|
||||||
sinfo.shmseg = (unsigned long) -1;
|
sinfo.shmseg = (unsigned long) -1;
|
||||||
sinfo.shmall = (unsigned long) -1;
|
sinfo.shmall = (unsigned long) -1;
|
||||||
if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, who_e,
|
if ((r = sys_datacopy(SELF, (vir_bytes)&sinfo, m->m_source,
|
||||||
(vir_bytes)ds, sizeof(sinfo))) != OK)
|
buf, sizeof(sinfo))) != OK)
|
||||||
return r;
|
return r;
|
||||||
if (shm_list_nr > 0)
|
if (shm_list_nr > 0)
|
||||||
m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
|
m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
|
||||||
@ -352,13 +339,13 @@ int do_shmctl(message *m)
|
|||||||
s_info.shm_tot = 0;
|
s_info.shm_tot = 0;
|
||||||
for (i = 0; i < shm_list_nr; i++)
|
for (i = 0; i < shm_list_nr; i++)
|
||||||
s_info.shm_tot +=
|
s_info.shm_tot +=
|
||||||
shm_list[i].shmid_ds.shm_segsz/PAGE_SIZE;
|
shm_list[i].shmid_ds.shm_segsz / PAGE_SIZE;
|
||||||
s_info.shm_rss = s_info.shm_tot;
|
s_info.shm_rss = s_info.shm_tot;
|
||||||
s_info.shm_swp = 0;
|
s_info.shm_swp = 0;
|
||||||
s_info.swap_attempts = 0;
|
s_info.swap_attempts = 0;
|
||||||
s_info.swap_successes = 0;
|
s_info.swap_successes = 0;
|
||||||
if ((r = sys_datacopy(SELF, (vir_bytes)&s_info, who_e,
|
if ((r = sys_datacopy(SELF, (vir_bytes)&s_info, m->m_source,
|
||||||
(vir_bytes)ds, sizeof(s_info))) != OK)
|
buf, sizeof(s_info))) != OK)
|
||||||
return r;
|
return r;
|
||||||
if (shm_list_nr > 0)
|
if (shm_list_nr > 0)
|
||||||
m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
|
m->m_lc_ipc_shmctl.ret = shm_list_nr - 1;
|
||||||
@ -372,25 +359,26 @@ int do_shmctl(message *m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void list_shm_ds(void)
|
static void
|
||||||
|
list_shm_ds(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
printf("key\tid\tpage\n");
|
printf("key\tid\tpage\n");
|
||||||
for (i = 0; i < shm_list_nr; i++) {
|
for (i = 0; i < shm_list_nr; i++) {
|
||||||
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
|
if (!(shm_list[i].shmid_ds.shm_perm.mode & SHM_ALLOC))
|
||||||
continue;
|
continue;
|
||||||
printf("%ld\t%d\t%lx\n",
|
printf("%ld\t%d\t%lx\n",
|
||||||
shm_list[i].shmid_ds.shm_perm._key,
|
shm_list[i].shmid_ds.shm_perm._key,
|
||||||
IXSEQ_TO_IPCID(i, shm_list[i].shmid_ds.shm_perm),
|
IXSEQ_TO_IPCID(i, shm_list[i].shmid_ds.shm_perm),
|
||||||
shm_list[i].page);
|
shm_list[i].page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*===========================================================================*
|
int
|
||||||
* is_shm_nil *
|
is_shm_nil(void)
|
||||||
*===========================================================================*/
|
|
||||||
int is_shm_nil(void)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
return (shm_list_nr == 0);
|
return (shm_list_nr == 0);
|
||||||
}
|
}
|
||||||
|
@ -1,35 +1,34 @@
|
|||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
int check_perm(struct ipc_perm *req, endpoint_t who, int mode)
|
int
|
||||||
|
check_perm(struct ipc_perm * req, endpoint_t who, int mode)
|
||||||
{
|
{
|
||||||
int req_mode;
|
int req_mode;
|
||||||
int cur_mode;
|
int cur_mode;
|
||||||
uid_t uid = getnuid(who);
|
uid_t uid;
|
||||||
gid_t gid = getngid(who);
|
gid_t gid;
|
||||||
|
|
||||||
|
uid = getnuid(who);
|
||||||
|
gid = getngid(who);
|
||||||
mode &= 0666;
|
mode &= 0666;
|
||||||
|
|
||||||
/* is root? */
|
/* Root is allowed to do anything. */
|
||||||
if (uid == 0)
|
if (uid == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (uid == req->uid || uid == req->cuid) {
|
if (uid == req->uid || uid == req->cuid) {
|
||||||
/* same user */
|
/* Same user. */
|
||||||
req_mode = (req->mode >> 6) & 0x7;
|
req_mode = (req->mode >> 6) & 0x7;
|
||||||
cur_mode = (mode >> 6) & 0x7;
|
cur_mode = (mode >> 6) & 0x7;
|
||||||
} else if (gid == req->gid || gid == req->cgid) {
|
} else if (gid == req->gid || gid == req->cgid) {
|
||||||
/* same group */
|
/* Same group. */
|
||||||
req_mode = (req->mode >> 3) & 0x7;
|
req_mode = (req->mode >> 3) & 0x7;
|
||||||
cur_mode = (mode >> 3) & 0x7;
|
cur_mode = (mode >> 3) & 0x7;
|
||||||
} else {
|
} else {
|
||||||
/* other group */
|
/* Other user and group. */
|
||||||
req_mode = req->mode & 0x7;
|
req_mode = req->mode & 0x7;
|
||||||
cur_mode = mode & 0x7;
|
cur_mode = mode & 0x7;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_mode && ((cur_mode & req_mode) == cur_mode))
|
return (cur_mode && ((cur_mode & req_mode) == cur_mode));
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user