| 30 |
#include <sys/shm.h> |
#include <sys/shm.h> |
| 31 |
#include <sys/ipc.h> |
#include <sys/ipc.h> |
| 32 |
|
|
| 33 |
|
#ifdef _SEM_SEMUN_UNDEFINED |
| 34 |
|
union semun |
| 35 |
|
{ |
| 36 |
|
int val; /* Value for SETVAL */ |
| 37 |
|
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ |
| 38 |
|
unsigned short *array; /* Array for GETALL, SETALL */ |
| 39 |
|
struct seminfo *__buf; /* Buffer for IPC_INFO |
| 40 |
|
(Linux-specific) */ |
| 41 |
|
}; |
| 42 |
|
#endif // #ifdef _SEM_SEMUN_UNDEFINED |
| 43 |
|
|
| 44 |
#define ARTICLE_BLOCK_PER_SHM 400 // sizeof(ARTICLE_BLOCK) * ARTICLE_BLOCK_PER_SHM is the size of each shm segment to allocate |
#define ARTICLE_BLOCK_PER_SHM 400 // sizeof(ARTICLE_BLOCK) * ARTICLE_BLOCK_PER_SHM is the size of each shm segment to allocate |
| 45 |
#define ARTICLE_BLOCK_SHM_COUNT_LIMIT 256 // limited by length (8-bit) of proj_id in ftok(path, proj_id) |
#define ARTICLE_BLOCK_SHM_COUNT_LIMIT 256 // limited by length (8-bit) of proj_id in ftok(path, proj_id) |
| 46 |
#define ARTICLE_BLOCK_PER_POOL (ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT) |
#define ARTICLE_BLOCK_PER_POOL (ARTICLE_BLOCK_PER_SHM * ARTICLE_BLOCK_SHM_COUNT_LIMIT) |
| 338 |
key_t key; |
key_t key; |
| 339 |
size_t size; |
size_t size; |
| 340 |
void *p_shm; |
void *p_shm; |
| 341 |
|
union semun arg; |
| 342 |
|
int i; |
| 343 |
|
|
| 344 |
if (p_section_list_pool == NULL || p_trie_dict_section_by_name == NULL || p_trie_dict_section_by_sid == NULL) |
if (p_section_list_pool == NULL || p_trie_dict_section_by_name == NULL || p_trie_dict_section_by_sid == NULL) |
| 345 |
{ |
{ |
| 365 |
semid = semget(key, (int)size, IPC_CREAT | IPC_EXCL | 0600); |
semid = semget(key, (int)size, IPC_CREAT | IPC_EXCL | 0600); |
| 366 |
if (semid == -1) |
if (semid == -1) |
| 367 |
{ |
{ |
| 368 |
log_error("semget(section_list_pool, size = %d) error (%d)\n", size, errno); |
log_error("semget(section_list_pool_sem, size = %d) error (%d)\n", size, errno); |
| 369 |
return -3; |
return -3; |
| 370 |
} |
} |
| 371 |
|
|
| 372 |
|
// Initialize sem value to 0 |
| 373 |
|
arg.val = 0; |
| 374 |
|
for (i = 0; i < size; i++) |
| 375 |
|
{ |
| 376 |
|
if (semctl(semid, i, SETVAL, arg) == -1) |
| 377 |
|
{ |
| 378 |
|
log_error("semctl(section_list_pool_sem, SETVAL) error (%d)\n", errno); |
| 379 |
|
return -3; |
| 380 |
|
} |
| 381 |
|
} |
| 382 |
|
|
| 383 |
section_list_pool_semid = semid; |
section_list_pool_semid = semid; |
| 384 |
|
|
| 385 |
size = sizeof(shmid) + sizeof(SECTION_LIST) * BBS_max_section; |
size = sizeof(shmid) + sizeof(SECTION_LIST) * BBS_max_section; |
| 386 |
shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600); |
shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600); |
| 387 |
if (shmid == -1) |
if (shmid == -1) |
| 388 |
{ |
{ |
| 389 |
log_error("shmget(section_list_pool, size = %d) error (%d)\n", size, errno); |
log_error("shmget(section_list_pool_shm, size = %d) error (%d)\n", size, errno); |
| 390 |
return -3; |
return -3; |
| 391 |
} |
} |
| 392 |
p_shm = shmat(shmid, NULL, 0); |
p_shm = shmat(shmid, NULL, 0); |
| 1231 |
int section_list_try_rd_lock(SECTION_LIST *p_section, int wait_sec) |
int section_list_try_rd_lock(SECTION_LIST *p_section, int wait_sec) |
| 1232 |
{ |
{ |
| 1233 |
int index; |
int index; |
| 1234 |
struct sembuf sops[2]; |
struct sembuf sops[4]; |
| 1235 |
struct timespec timeout; |
struct timespec timeout; |
| 1236 |
int ret; |
int ret; |
| 1237 |
|
|
| 1241 |
return -2; |
return -2; |
| 1242 |
} |
} |
| 1243 |
|
|
| 1244 |
sops[0].sem_num = (unsigned short)index + 1; // w_sem of section index |
sops[0].sem_num = (unsigned short)(index * 2 + 1); // w_sem of section index |
| 1245 |
sops[0].sem_op = 0; // check if unlocked |
sops[0].sem_op = 0; // wait until unlocked |
| 1246 |
sops[0].sem_flg = 0; |
sops[0].sem_flg = 0; |
| 1247 |
|
|
| 1248 |
sops[1].sem_num = (unsigned short)index; // r_sem of section index |
sops[1].sem_num = (unsigned short)(index * 2); // r_sem of section index |
| 1249 |
sops[1].sem_op = 1; // lock |
sops[1].sem_op = 1; // lock |
| 1250 |
sops[1].sem_flg = SEM_UNDO; // undo on terminate |
sops[1].sem_flg = SEM_UNDO; // undo on terminate |
| 1251 |
|
|
| 1252 |
|
// Read lock on any specific section will also acquire single read lock on "all section" |
| 1253 |
|
// so that write lock on all section only need to acquire single write on on "all section" |
| 1254 |
|
// rather than to acquire multiple write locks on all the available sections. |
| 1255 |
|
if (index == BBS_max_section) |
| 1256 |
|
{ |
| 1257 |
|
sops[2].sem_num = BBS_max_section * 2 + 1; // w_sem of all section |
| 1258 |
|
sops[2].sem_op = 0; // wait until unlocked |
| 1259 |
|
sops[2].sem_flg = 0; |
| 1260 |
|
|
| 1261 |
|
sops[3].sem_num = BBS_max_section * 2; // r_sem of all section |
| 1262 |
|
sops[3].sem_op = 1; // lock |
| 1263 |
|
sops[3].sem_flg = SEM_UNDO; // undo on terminate |
| 1264 |
|
} |
| 1265 |
|
|
| 1266 |
timeout.tv_sec = wait_sec; |
timeout.tv_sec = wait_sec; |
| 1267 |
timeout.tv_nsec = 0; |
timeout.tv_nsec = 0; |
| 1268 |
|
|
| 1269 |
ret = semtimedop(section_list_pool_semid, sops, 2, &timeout); |
ret = semtimedop(section_list_pool_semid, sops, (index == BBS_max_section ? 4 : 2), &timeout); |
| 1270 |
|
if (ret == -1 && errno != EAGAIN && errno != EINTR) |
| 1271 |
|
{ |
| 1272 |
|
log_error("semtimedop(index = %d, lock read) error %d\n", index, errno); |
| 1273 |
|
} |
| 1274 |
|
|
| 1275 |
return ret; |
return ret; |
| 1276 |
} |
} |
| 1288 |
return -2; |
return -2; |
| 1289 |
} |
} |
| 1290 |
|
|
| 1291 |
sops[0].sem_num = (unsigned short)index + 1; // w_sem of section index |
sops[0].sem_num = (unsigned short)(index * 2 + 1); // w_sem of section index |
| 1292 |
sops[0].sem_op = 0; // check if unlocked |
sops[0].sem_op = 0; // wait until unlocked |
| 1293 |
sops[0].sem_flg = 0; |
sops[0].sem_flg = 0; |
| 1294 |
|
|
| 1295 |
sops[1].sem_num = (unsigned short)index + 1; // w_sem of section index |
sops[1].sem_num = (unsigned short)(index * 2 + 1); // w_sem of section index |
| 1296 |
sops[1].sem_op = 1; // lock |
sops[1].sem_op = 1; // lock |
| 1297 |
sops[1].sem_flg = SEM_UNDO; // undo on terminate |
sops[1].sem_flg = SEM_UNDO; // undo on terminate |
| 1298 |
|
|
| 1299 |
sops[2].sem_num = (unsigned short)index; // r_sem of section index |
sops[2].sem_num = (unsigned short)(index * 2); // r_sem of section index |
| 1300 |
sops[1].sem_op = 0; // wait until unlocked |
sops[2].sem_op = 0; // wait until unlocked |
| 1301 |
sops[1].sem_flg = 0; |
sops[2].sem_flg = 0; |
| 1302 |
|
|
| 1303 |
timeout.tv_sec = wait_sec; |
timeout.tv_sec = wait_sec; |
| 1304 |
timeout.tv_nsec = 0; |
timeout.tv_nsec = 0; |
| 1305 |
|
|
| 1306 |
ret = semtimedop(section_list_pool_semid, sops, 3, &timeout); |
ret = semtimedop(section_list_pool_semid, sops, 3, &timeout); |
| 1307 |
|
if (ret == -1 && errno != EAGAIN && errno != EINTR) |
| 1308 |
|
{ |
| 1309 |
|
log_error("semtimedop(index = %d, lock write) error %d\n", index, errno); |
| 1310 |
|
} |
| 1311 |
|
|
| 1312 |
return ret; |
return ret; |
| 1313 |
} |
} |
| 1315 |
int section_list_rd_unlock(SECTION_LIST *p_section) |
int section_list_rd_unlock(SECTION_LIST *p_section) |
| 1316 |
{ |
{ |
| 1317 |
int index; |
int index; |
| 1318 |
struct sembuf sops[1]; |
struct sembuf sops[2]; |
| 1319 |
int ret; |
int ret; |
| 1320 |
|
|
| 1321 |
index = get_section_index(p_section); |
index = get_section_index(p_section); |
| 1324 |
return -2; |
return -2; |
| 1325 |
} |
} |
| 1326 |
|
|
| 1327 |
sops[0].sem_num = (unsigned short)index; // r_sem of section index |
sops[0].sem_num = (unsigned short)(index * 2); // r_sem of section index |
| 1328 |
sops[0].sem_op = -1; // unlock |
sops[0].sem_op = -1; // unlock |
| 1329 |
sops[0].sem_flg = IPC_NOWAIT; // no wait |
sops[0].sem_flg = IPC_NOWAIT | SEM_UNDO; // no wait |
| 1330 |
|
|
| 1331 |
ret = semop(section_list_pool_semid, sops, 1); |
// The same reason as section_list_try_rd_lock() |
| 1332 |
|
if (index == BBS_max_section) |
| 1333 |
|
{ |
| 1334 |
|
sops[1].sem_num = BBS_max_section * 2; // r_sem of all section |
| 1335 |
|
sops[1].sem_op = -1; // unlock |
| 1336 |
|
sops[1].sem_flg = IPC_NOWAIT | SEM_UNDO; // no wait |
| 1337 |
|
} |
| 1338 |
|
|
| 1339 |
|
ret = semop(section_list_pool_semid, sops, (index == BBS_max_section ? 2 : 1)); |
| 1340 |
|
if (ret == -1 && errno != EAGAIN && errno != EINTR) |
| 1341 |
|
{ |
| 1342 |
|
log_error("semop(index = %d, unlock read) error %d\n", index, errno); |
| 1343 |
|
} |
| 1344 |
|
|
| 1345 |
return ret; |
return ret; |
| 1346 |
} |
} |
| 1357 |
return -2; |
return -2; |
| 1358 |
} |
} |
| 1359 |
|
|
| 1360 |
sops[0].sem_num = (unsigned short)index + 1; // w_sem of section index |
sops[0].sem_num = (unsigned short)(index * 2 + 1); // w_sem of section index |
| 1361 |
sops[0].sem_op = -1; // unlock |
sops[0].sem_op = -1; // unlock |
| 1362 |
sops[0].sem_flg = IPC_NOWAIT; // no wait |
sops[0].sem_flg = IPC_NOWAIT | SEM_UNDO; // no wait |
| 1363 |
|
|
| 1364 |
ret = semop(section_list_pool_semid, sops, 1); |
ret = semop(section_list_pool_semid, sops, 1); |
| 1365 |
|
if (ret == -1 && errno != EAGAIN && errno != EINTR) |
| 1366 |
|
{ |
| 1367 |
|
log_error("semop(index = %d, unlock write) error %d\n", index, errno); |
| 1368 |
|
} |
| 1369 |
|
|
| 1370 |
return ret; |
return ret; |
| 1371 |
} |
} |