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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
--- src/sema.c.orig Sun Jul 21 21:13:59 2002
+++ src/sema.c Mon Jul 22 19:30:15 2002
@@ -22,6 +22,10 @@
# include <config.h>
#endif
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -57,6 +61,11 @@
#include "uaddr.h"
#include "status.h"
+/* interval between busy wait tries measured in microseconds */
+#define MUTEX_BUSY_WAIT_TIME 5000
+
+pthread_mutex_t *semaphore_mutex = PTHREAD_MUTEX_INITIALIZER;
+
/***********************************************************************/
/* the following functions manage the bandwidth upload limit */
/* The system is build on 2 semaphores and 1 file */
@@ -100,6 +109,8 @@
int semid;
+ lp_mutex_init_(&semaphore_mutex, NULL);
+
fd=open(keyfile,O_CREAT|O_WRONLY|O_EXCL,0600); /* create the file if not exists */
if(fd==-1)
{
@@ -131,7 +142,11 @@
{
close(fd);
/* a key exist */
+#if !(defined(BSD) && (BSD >= 199103))
semid=semget(key,0,IPC_ALLOC);
+#else
+ semid=semget(key,0,IPC_STAT);
+#endif
if(semid==-1)
goto create_new_sema;
printf("current sema found.\n");
@@ -293,8 +308,13 @@
void check_sema_master(int semid)
{
struct sembuf sb={0,-1,IPC_NOWAIT|SEM_UNDO}; /* master sema */
+ int result;
+
+ (void) lp_mutex_lock_(semaphore_mutex);
+ result = semop(semid,&sb,1);
+ (void) lp_mutex_unlock_(semaphore_mutex);
- if(semop(semid,&sb,1)==0)
+ if (result==0)
{
/* to get slice, the function checks if the clock thread still runs */
create_sema_master(semid);
@@ -308,15 +328,29 @@
/*******************************************/
void get_slice(int semid, SPD_SEMA semnum)
{
+#if !(defined(BSD) && (BSD >= 199103))
+ struct sembuf local={0,-1,0}; /* slave sema */
+#else
+ struct sembuf local={0,-1,0|IPC_NOWAIT}; /* slave sema */
+#endif
+ local.sem_num=semnum;
+
+ (void) lp_mutex_lock_(semaphore_mutex);
while(1)
{
- struct sembuf local={0,-1,0}; /* slave sema */
-
- local.sem_num=semnum;
- if(semop(semid,&local,1)==0)
- {
- /* we have what we want */
- return;
+ switch (semop(semid,&local,1)) {
+ case 0: (void) lp_mutex_unlock_(semaphore_mutex);
+ /* we have what we want */
+ return;
+ break;
+ case -1: switch(errno) {
+ case EAGAIN: /* triggers busy wait */
+ case EINTR: /* interrupted by system call, try again */
+ pthread_yield();
+ usleep(MUTEX_BUSY_WAIT_TIME); /* busy wait with a small time out */
+ continue;
+ break;
+ }
}
}
}
@@ -368,9 +402,26 @@
/******************************/
void lock_ul_slot_controler(int semid)
{
+#if !(defined(BSD) && (BSD >= 199103))
struct sembuf get_ul_ctrl={UL_SLOT_SEMA,-1,SEM_UNDO};
+#else
+ struct sembuf get_ul_ctrl={UL_SLOT_SEMA,-1,SEM_UNDO|IPC_NOWAIT};
+#endif
+
+ (void) lp_mutex_lock_(semaphore_mutex);
+repeat:
/* lock the UL slot controler */
- semop(semid,&get_ul_ctrl,1);
+ if (semop(semid,&get_ul_ctrl,1)==-1)
+ switch(errno)
+ {
+ case EAGAIN: /* triggers busy wait */
+ case EINTR: /* interrupted by system call, try again */
+ pthread_yield();
+ usleep(MUTEX_BUSY_WAIT_TIME); /* busy wait with a small time out */
+ goto repeat;
+ break;
+ }
+ (void) lp_mutex_unlock_(semaphore_mutex);
}
/*********************************/
@@ -526,11 +577,28 @@
perror("free_one_ul_slot");
}
#else
+# if !(defined(BSD) && (BSD >= 199103))
struct sembuf free_one_ul_slot_op={UL_SLOT_BUSY_SEMA,-1,SEM_UNDO};
- if(semop(semid,&free_one_ul_slot_op,1)==-1)
- {
- perror("free_one_ul_slot");
+# else
+ struct sembuf free_one_ul_slot_op={UL_SLOT_BUSY_SEMA,-1,SEM_UNDO|IPC_NOWAIT};
+# endif
+
+ (void) lp_mutex_lock_(semaphore_mutex);
+repeat:
+ if(semop(semid,&free_one_ul_slot_op,1)==-1) {
+ switch(errno) {
+ case EAGAIN: /* triggers busy wait */
+ case EINTR: /* interrupted by system call, try again */
+ pthread_yield();
+ usleep(MUTEX_BUSY_WAIT_TIME); /* busy wait with a small time out */
+ goto repeat;
+ break;
+ default:
+ perror("free_one_ul_slot");
+ break;
+ }
}
+ (void) lp_mutex_unlock_(semaphore_mutex);
#endif
nb_local_ul--;
}
|