summaryrefslogtreecommitdiff
path: root/minix/lib/libc/sys/sem.c
blob: 958b11355fb12178b372cc7d95f8452865394926 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#define _SYSTEM	1
#define _MINIX_SYSTEM	1

#include <sys/cdefs.h>
#include <lib.h>
#include "namespace.h"

#include <lib.h>
#include <minix/rs.h>

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>

static int get_ipc_endpt(endpoint_t *pt)
{
	return minix_rs_lookup("ipc", pt);
}

/* Get semaphore.  */
int semget(key_t key, int nsems, int semflag)
{
	message m;
	endpoint_t ipc_pt;
	int r;

	if (get_ipc_endpt(&ipc_pt) != OK) {
		errno = ENOSYS;
		return -1;
	}

	memset(&m, 0, sizeof(m));
	m.m_lc_ipc_semget.key = key;
	m.m_lc_ipc_semget.nr = nsems;
	m.m_lc_ipc_semget.flag = semflag;

	r = _syscall(ipc_pt, IPC_SEMGET, &m);
	if (r != OK)
		return r;

	return m.m_lc_ipc_semget.retid;
}
 
/* Semaphore control operation.  */
int semctl(int semid, int semnum, int cmd, ...)
{
	message m;
	endpoint_t ipc_pt;
	va_list ap;
	int r;

	if (get_ipc_endpt(&ipc_pt) != OK) {
		errno = ENOSYS;
		return -1;
	}

	memset(&m, 0, sizeof(m));
	m.m_lc_ipc_semctl.id = semid;
	m.m_lc_ipc_semctl.num = semnum;
	m.m_lc_ipc_semctl.cmd = cmd;
	va_start(ap, cmd);
	switch (cmd) {
	case SETVAL:
		m.m_lc_ipc_semctl.opt = (vir_bytes)va_arg(ap, int);
		break;
	case IPC_STAT:
	case IPC_SET:
	case IPC_INFO:
	case SEM_INFO:
	case SEM_STAT:
	case GETALL:
	case SETALL:
		m.m_lc_ipc_semctl.opt = (vir_bytes)va_arg(ap, void *);
		break;
	default:
		m.m_lc_ipc_semctl.opt = 0;
		break;
	}
	va_end(ap); 

	r = _syscall(ipc_pt, IPC_SEMCTL, &m);
	if ((r != -1) && (cmd == GETNCNT || cmd == GETZCNT || cmd == GETPID ||
		cmd == GETVAL || cmd == IPC_INFO || cmd == SEM_INFO ||
		cmd == SEM_STAT))
		return m.m_lc_ipc_semctl.ret;
	return r;
}

/* Operate on semaphore.  */
int semop(int semid, struct sembuf *sops, size_t nsops)
{
	message m;
	endpoint_t ipc_pt;

	if (get_ipc_endpt(&ipc_pt) != OK) {
		errno = ENOSYS;
		return -1;
	}

	memset(&m, 0, sizeof(m));
	m.m_lc_ipc_semop.id = semid;
	m.m_lc_ipc_semop.ops = sops;
	m.m_lc_ipc_semop.size = nsops;

	return _syscall(ipc_pt, IPC_SEMOP, &m);
}