Removed fork()
[meinos.git] / apps / lib / stdlibc / sem.c
blob4655dc600fa05e0ff71cd4eb63dc3b55a35bd459
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/sem.h>
20 #include <sys/ipc.h>
21 #include <sys/types.h>
22 #include <time.h>
23 #include <stdarg.h>
24 #include <errno.h>
25 #include <syscall.h>
27 #define sem_get(key) syscall_call(SYSCALL_IPC_SEM_GET,1,key)
28 #define sem_create(key,nsems,flags) syscall_call(SYSCALL_IPC_SEM_CREATE,4,key,nsems,flags,time(NULL))
29 #define sem_op(id,ops,nops) syscall_call(SYSCALL_IPC_SEM_OP,4,id,ops,nops,time(NULL))
30 #define sem_getval(id,num) syscall_call(SYSCALL_IPC_SEM_GETVAL,2,id,num)
31 #define sem_setval(id,num,val) syscall_call(SYSCALL_IPC_SEM_SETVAL,4,id,num,val,time(NULL))
32 #define sem_getpid(id,num) syscall_call(SYSCALL_IPC_SEM_GETPID,2,id,num)
33 #define sem_getcnt(id,num,type) syscall_call(SYSCALL_IPC_SEM_GETCNT,3,id,num,type)
34 #define sem_getall(id,buf) syscall_call(SYSCALL_IPC_SEM_GETALL,2,id,buf)
35 #define sem_setall(id,buf) syscall_call(SYSCALL_IPC_SEM_SETALL,3,id,buf,time(NULL))
36 #define sem_stat(id,uid,gid,cuid,cgid,mode,nsems,otime,ctime) syscall_call(SYSCALL_IPC_SEM_STAT,9,id,uid,gid,cuid,cgid,mode,nsems,otime,ctime)
37 #define sem_set(id,uid,gid,mode) syscall_call(SYSCALL_IPC_SEM_SET,5,id,uid,gid,mode,time(NULL))
38 #define sem_destroy(id) syscall_call(SYSCALL_IPC_SEM_DESTROY,1,id)
40 int semget(key_t key,int nsems,int flags) {
41 int ret;
42 if ((flags&IPC_CREAT) || key==IPC_PRIVATE) ret = sem_create(key,nsems,flags&0777);
43 if (!(flags&IPC_CREAT) || ret<0) ret = sem_get(key);
44 errno = ret<0?-ret:0;
45 return ret<0?-1:ret;
48 int semop(int id,struct sembuf *ops,size_t nops) {
49 ssize_t ret;
50 do {
51 int sleep = 0;
52 ret = sem_op(id,ops,nops);
53 while (sleep);
54 if (ret<0) {
55 errno = ret;
56 return -1;
59 while (ret<nops);
60 errno = 0;
61 return 0;
64 int semctl(int id,int num,int cmd,...) {
65 va_list args;
66 int ret;
68 va_start(args,cmd);
69 if (cmd==GETVAL) ret = sem_getval(id,num);
70 else if (cmd==SETVAL) ret = sem_setval(id,num,va_arg(args,int));
71 else if (cmd==GETPID) ret = sem_getpid(id,num);
72 else if (cmd==GETNCNT) ret = sem_getcnt(id,num,'n');
73 else if (cmd==GETZCNT) ret = sem_getcnt(id,num,'z');
74 else if (cmd==GETALL) ret = sem_getall(id,va_arg(args,unsigned short*));
75 else if (cmd==SETALL) ret = sem_setall(id,va_arg(args,unsigned short*));
76 else if (cmd==IPC_STAT) {
77 struct semid_ds *buf = va_arg(args,struct semid_ds*);
78 ret = sem_stat(id,&(buf->sem_perm.uid),&(buf->sem_perm.gid),&(buf->sem_perm.cuid),&(buf->sem_perm.cgid),&(buf->sem_perm.mode),&(buf->sem_nsems),&(buf->sem_otime),&(buf->sem_ctime));
80 else if (cmd==IPC_SET) {
81 struct semid_ds *buf = va_arg(args,struct semid_ds*);
82 ret = sem_set(id,buf->sem_perm.uid,buf->sem_perm.gid,buf->sem_perm.mode);
84 else if (cmd==IPC_RMID) ret = sem_destroy(id);
85 else ret = -EINVAL;
86 errno = ret<0?-ret:0;
87 return ret<0?-1:0;