Ticket #2657: draft-shm-002.patch
File draft-shm-002.patch, 22.9 KB (added by , 14 years ago) |
---|
-
new file headers/posix/sys/shm.h
From 119c3a77e40c392ba4c5eb6a26c1b6988182ed82 Mon Sep 17 00:00:00 2001 From: David Höppner <0xffea@gmail.com> Date: Sun, 26 Dec 2010 18:58:43 +0100 Subject: [PATCH] <sys/shm.h> --- headers/posix/sys/shm.h | 46 ++ headers/private/kernel/posix/xsi_shared_memory.h | 29 ++ headers/private/system/syscalls.h | 7 + src/system/kernel/main.cpp | 2 + src/system/kernel/posix/Jamfile | 1 + src/system/kernel/posix/xsi_shared_memory.cpp | 547 ++++++++++++++++++++++ src/system/kernel/syscalls.cpp | 1 + src/system/libroot/posix/sys/Jamfile | 1 + src/system/libroot/posix/sys/xsi_shm.cpp | 51 ++ src/tests/system/libroot/posix/Jamfile | 1 + src/tests/system/libroot/posix/xsi_shm_test1.cpp | 143 ++++++ 11 files changed, 829 insertions(+), 0 deletions(-) create mode 100644 headers/posix/sys/shm.h create mode 100644 headers/private/kernel/posix/xsi_shared_memory.h create mode 100644 src/system/kernel/posix/xsi_shared_memory.cpp create mode 100644 src/system/libroot/posix/sys/xsi_shm.cpp create mode 100644 src/tests/system/libroot/posix/xsi_shm_test1.cpp diff --git a/headers/posix/sys/shm.h b/headers/posix/sys/shm.h new file mode 100644 index 0000000..a7d5968
- + 1 /* 2 * Copyright 2011 Haiku Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _SYS_SHM_H 6 #define _SYS_SHM_H 7 8 9 #include <sys/ipc.h> 10 #include <sys/types.h> 11 12 13 /* Message Flags */ 14 #define SHM_RDONLY 01000 /* attach read-only (else read-write) */ 15 #define SHM_RND 02000 /* rounds attach address to SHMLBA */ 16 17 #define SHMLBA 1024 18 19 /* shmat() error return code */ 20 #define SHM_FAILED ((void*)-1) 21 22 23 typedef unsigned long shmatt_t; 24 25 struct shmid_ds { 26 struct ipc_perm shm_perm; 27 size_t shm_segsz; 28 pid_t shm_lpid; 29 pid_t shm_cpid; 30 shmatt_t shm_nattch; 31 time_t shm_atime; 32 time_t shm_dtime; 33 time_t shm_ctime; 34 }; 35 36 37 __BEGIN_DECLS 38 39 void* shmat(int id, const void* address, int flags); 40 int shmctl(int id, int command, struct shmid_ds* mds); 41 int shmdt(const void* address); 42 int shmget(key_t key, size_t size, int flags); 43 44 __END_DECLS 45 46 #endif /* _SYS_SHM_H */ -
new file headers/private/kernel/posix/xsi_shared_memory.h
diff --git a/headers/private/kernel/posix/xsi_shared_memory.h b/headers/private/kernel/posix/xsi_shared_memory.h new file mode 100644 index 0000000..9d845f1
- + 1 /* 2 * Copyright 2011, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef KERNEL_XSI_SHARED_MEMORY_H 6 #define KERNEL_XSI_SHARED_MEMORY_H 7 8 9 #include <sys/shm.h> 10 #include <sys/cdefs.h> 11 12 #include <OS.h> 13 14 #include <kernel.h> 15 16 17 __BEGIN_DECLS 18 19 extern void xsi_shm_init(); 20 21 /* user calls */ 22 status_t _user_xsi_shmat(int id, const void* address, int, void** rAddress); 23 int _user_xsi_shmctl(int id, int command, struct shmid_ds* mds); 24 int _user_xsi_shmdt(const void* address); 25 int _user_xsi_shmget(key_t key, size_t size, int flags); 26 27 __END_DECLS 28 29 #endif /* KERNEL_XSI_SHARED_MEMORY_H */ -
headers/private/system/syscalls.h
diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index cd510bd..2ebd38b 100644
a b struct _sem_t; 35 35 struct sembuf; 36 36 union semun; 37 37 struct sigaction; 38 struct shmid_ds; 38 39 struct stat; 39 40 struct system_profiler_parameters; 40 41 … … extern int _kern_xsi_msgsnd(int messageQueueID, 125 126 const void *messagePointer, size_t messageSize, 126 127 int messageFlags); 127 128 129 /* POSIX XSI shared memory syscalls */ 130 extern status_t _kern_xsi_shmat(int a, const void* memoryPointer, int b, void **addr); 131 extern int _kern_xsi_shmctl(int a, int b, struct shmid_ds *memoryDs); 132 extern int _kern_xsi_shmdt(const void *memoryPointer); 133 extern int _kern_xsi_shmget(key_t key, size_t size, int flags); 134 128 135 /* team & thread syscalls */ 129 136 extern thread_id _kern_load_image(const char* const* flatArgs, 130 137 size_t flatArgsSize, int32 argCount, int32 envCount, -
src/system/kernel/main.cpp
diff --git a/src/system/kernel/main.cpp b/src/system/kernel/main.cpp index eca43c7..649e0a2 100644
a b 42 42 #include <posix/realtime_sem.h> 43 43 #include <posix/xsi_message_queue.h> 44 44 #include <posix/xsi_semaphore.h> 45 #include <posix/xsi_shared_memory.h> 45 46 #include <real_time_clock.h> 46 47 #include <sem.h> 47 48 #include <smp.h> … … _start(kernel_args *bootKernelArgs, int currentCPU) 190 191 realtime_sem_init(); 191 192 xsi_sem_init(); 192 193 xsi_msg_init(); 194 xsi_shm_init(); 193 195 194 196 // Start a thread to finish initializing the rest of the system. Note, 195 197 // it won't be scheduled before calling scheduler_start() (on any CPU). -
src/system/kernel/posix/Jamfile
diff --git a/src/system/kernel/posix/Jamfile b/src/system/kernel/posix/Jamfile index 1eb2f51..ffb2f38 100644
a b KernelMergeObject kernel_posix.o : 6 6 realtime_sem.cpp 7 7 xsi_message_queue.cpp 8 8 xsi_semaphore.cpp 9 xsi_shared_memory.cpp 9 10 10 11 : $(TARGET_KERNEL_PIC_CCFLAGS) 11 12 ; -
new file src/system/kernel/posix/xsi_shared_memory.cpp
diff --git a/src/system/kernel/posix/xsi_shared_memory.cpp b/src/system/kernel/posix/xsi_shared_memory.cpp new file mode 100644 index 0000000..25bf778
- + 1 /* 2 * Copyright 2011, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * David Höppner <0xffea@gmail.com> 7 */ 8 9 10 #include <posix/xsi_shared_memory.h> 11 12 #include <stdio.h> 13 14 #include <sys/ipc.h> 15 #include <sys/types.h> 16 17 #include <kernel/lock.h> 18 #include <kernel/debug.h> 19 #include <kernel/team.h> 20 #include <kernel/thread.h> 21 #include <kernel/heap.h> 22 23 #include <vm/vm.h> 24 #include <vm/VMAddressSpace.h> 25 #include <vm/VMArea.h> 26 #include <vm/VMCache.h> 27 28 #include <util/AutoLock.h> 29 #include <util/DoublyLinkedList.h> 30 #include <util/OpenHashTable.h> 31 32 33 #define TRACE_XSI_SHM 34 #ifdef TRACE_XSI_SHM 35 # define TRACE(x) dprintf x 36 #else 37 # define TRACE(x) /* nothing */ 38 #endif 39 40 #define MAX_XSI_SHARED_MEMORY_COUNT 64 41 #define MIN_XSI_SHARED_MEMORY_SIZE 1 42 #define MAX_XSI_SHARED_MEMORY_SIZE 256*1024*1024 43 #define MAX_XSI_SHARED_MEMORY_ATTACH 128 44 45 46 static mutex sXsiSharedMemoryLock = MUTEX_INITIALIZER("Global POSIX XSI Shared Memory Lock"); 47 static int sSharedMemoryCount = 0; 48 static uint32 sGlobalSequenceNumber = 1; 49 50 51 class SharedMemoryEntry { 52 public: 53 SharedMemoryEntry(key_t key, size_t size, int flags) 54 : 55 fKey(key), 56 fSize(size) 57 { 58 fIdDataStructure.shm_segsz = fSize; 59 60 fIdDataStructure.shm_cpid = getpid(); 61 fIdDataStructure.shm_lpid = fIdDataStructure.shm_nattch = 0; 62 fIdDataStructure.shm_atime = fIdDataStructure.shm_dtime = 0; 63 fIdDataStructure.shm_ctime = real_time_clock(); 64 65 fIdDataStructure.shm_perm.uid = fIdDataStructure.shm_perm.cuid = geteuid(); 66 fIdDataStructure.shm_perm.gid = fIdDataStructure.shm_perm.cgid = getegid(); 67 fIdDataStructure.shm_perm.mode = flags & 0x1ff; 68 } 69 70 status_t Init() 71 { 72 status_t status = VMCacheFactory::CreateAnonymousCache(fCache, 1, 0, 0, true, 73 VM_PRIORITY_SYSTEM); 74 if (status != B_OK) 75 return ENOMEM; 76 77 fCache->temporary = 1; 78 fCache->virtual_end = PAGE_ALIGN(fSize); 79 fCache->committed_size = 0; 80 81 snprintf(fAreaName, B_OS_NAME_LENGTH, "xsi_shared_memory%ld", sGlobalSequenceNumber); 82 83 SetId(); 84 85 atomic_add(&sGlobalSequenceNumber, 1); 86 atomic_add(&sSharedMemoryCount, 1); 87 88 return B_OK; 89 } 90 91 ~SharedMemoryEntry() 92 { 93 status_t status; 94 95 for (VMArea* area = fCache->areas; area != NULL; area = area->cache_next) { 96 status = vm_delete_area(VMAddressSpace::CurrentID(), area->id, true); 97 if (status != B_OK) { 98 return; 99 } 100 } 101 102 fCache->Delete(); 103 104 atomic_add(&sSharedMemoryCount, -1); 105 } 106 107 void SetId(); 108 109 bool HasPermission() const 110 { 111 uid_t uid = geteuid(); 112 if (uid == 0 113 || uid == fIdDataStructure.shm_perm.uid 114 || uid == fIdDataStructure.shm_perm.cuid) 115 return true; 116 117 return false; 118 } 119 120 bool HasReadPermission() const 121 { 122 if (fIdDataStructure.shm_perm.mode & S_IROTH) 123 return true; 124 125 uid_t uid = geteuid(); 126 if (uid == 0 || (uid == fIdDataStructure.shm_perm.uid 127 && (fIdDataStructure.shm_perm.mode & S_IRUSR) != 0)) 128 return true; 129 130 gid_t gid = getegid(); 131 if (uid == 0 || (gid == fIdDataStructure.shm_perm.gid 132 && (fIdDataStructure.shm_perm.mode & S_IRGRP) != 0)) 133 return true; 134 135 return false; 136 } 137 138 int Id() const 139 { 140 return fId; 141 } 142 143 key_t Key() const 144 { 145 return fKey; 146 } 147 148 VMCache* Cache() const 149 { 150 return fCache; 151 } 152 153 char* AreaName() 154 { 155 return fAreaName; 156 } 157 158 size_t Size() const 159 { 160 return fSize; 161 } 162 163 struct shmid_ds* IdDataStructure() 164 { 165 return &fIdDataStructure; 166 } 167 168 SharedMemoryEntry*& Link() 169 { 170 return fLink; 171 } 172 173 private: 174 int fId; 175 key_t fKey; 176 VMCache* fCache; 177 char fAreaName[B_OS_NAME_LENGTH]; 178 size_t fSize; 179 struct shmid_ds fIdDataStructure; 180 SharedMemoryEntry* fLink; 181 }; 182 183 struct XsiSharedMemoryEntryHashTableDefinition { 184 typedef int KeyType; 185 typedef SharedMemoryEntry ValueType; 186 187 size_t HashKey (const int id) const 188 { 189 return (size_t)(id); 190 } 191 192 size_t Hash(SharedMemoryEntry* variable) const 193 { 194 return (size_t)HashKey(variable->Id()); 195 } 196 197 bool Compare(const int id, SharedMemoryEntry* variable) const 198 { 199 return (int)id == (int)variable->Id(); 200 } 201 202 SharedMemoryEntry*& GetLink(SharedMemoryEntry* variable) const 203 { 204 return variable->Link(); 205 } 206 }; 207 208 typedef BOpenHashTable<XsiSharedMemoryEntryHashTableDefinition> SharedMemoryEntryTable; 209 static SharedMemoryEntryTable sSharedMemoryEntryTable; 210 211 212 class Ipc { 213 public: 214 Ipc(key_t key, size_t size) 215 : 216 fKey(key), 217 fSize(size), 218 fSharedMemoryId(-1) 219 { 220 } 221 222 key_t Key() const 223 { 224 return fKey; 225 } 226 227 size_t Size() const 228 { 229 return fSize; 230 } 231 232 int SharedMemoryId() const 233 { 234 return fSharedMemoryId; 235 } 236 237 void SetSharedMemoryId(int id) 238 { 239 fSharedMemoryId = id; 240 } 241 242 Ipc*& Link() 243 { 244 return fLink; 245 } 246 247 private: 248 key_t fKey; 249 size_t fSize; 250 int fSharedMemoryId; 251 Ipc* fLink; 252 }; 253 254 struct IpcHashTableDefinition { 255 typedef key_t KeyType; 256 typedef Ipc ValueType; 257 258 size_t HashKey (const key_t key) const 259 { 260 return (size_t)(key); 261 } 262 263 size_t Hash(Ipc* variable) const 264 { 265 return (size_t)HashKey(variable->Key()); 266 } 267 268 bool Compare(const key_t key, Ipc* variable) const 269 { 270 return (key_t)key == (key_t)variable->Key(); 271 } 272 273 Ipc*& GetLink(Ipc* variable) const 274 { 275 return variable->Link(); 276 } 277 }; 278 279 static BOpenHashTable<IpcHashTableDefinition> sIpcTable; 280 281 282 void 283 SharedMemoryEntry::SetId() 284 { 285 fId = real_time_clock(); 286 287 while (true) { 288 if (sSharedMemoryEntryTable.Lookup(fId) == NULL) 289 break; 290 fId = (fId + 1) % INT_MAX; 291 } 292 } 293 294 295 // #pragma mark - Kernel exported API 296 297 298 void 299 xsi_shm_init() 300 { 301 status_t status = sSharedMemoryEntryTable.Init(); 302 if (status != B_OK) 303 panic("xsi_shm_init(): Failed to initialize shared memory hash table!\n"); 304 305 status = sIpcTable.Init(); 306 if (status != B_OK) 307 panic("xsi_shm_init(): Failed to initialize ipc key hash table!\n"); 308 } 309 310 311 status_t 312 _user_xsi_shmat(int id, const void* address, int flags, void** _returnAddress) 313 { 314 TRACE(("shmat: id = %d, address = %p, flags = %d\n", 315 id, address, flags)); 316 317 MutexLocker _(sXsiSharedMemoryLock); 318 319 SharedMemoryEntry* entry = sSharedMemoryEntryTable.Lookup(id); 320 if (entry == NULL) 321 return EINVAL; 322 323 struct shmid_ds* idDataStructure = entry->IdDataStructure(); 324 if (idDataStructure->shm_nattch >= MAX_XSI_SHARED_MEMORY_ATTACH) 325 return EMFILE; 326 327 int protection = B_READ_AREA | B_WRITE_AREA | B_SHARED_AREA; 328 if ((flags & SHM_RDONLY) != 0) 329 protection &= ~B_WRITE_AREA; 330 331 uint32 addressSpec = B_ANY_ADDRESS; 332 if (address != NULL) { 333 if ((flags & SHM_RND) != 0) { 334 // TODO address = (void *) (addr - ((uintptr_t) addr % SHMLBA)); 335 return EINVAL; 336 } else { 337 address = (void *)address; 338 addressSpec = B_EXACT_ADDRESS; 339 } 340 341 if (!IS_USER_ADDRESS(address)) 342 return B_BAD_ADDRESS; 343 } 344 345 VMAddressSpace* targetAddressSpace = VMAddressSpace::GetCurrent(); 346 if (targetAddressSpace == NULL) 347 return EINVAL; 348 349 size_t size = PAGE_ALIGN(entry->Size()); 350 351 virtual_address_restrictions addressRestrictions = {}; 352 addressRestrictions.address = NULL; 353 addressRestrictions.address_specification = addressSpec; 354 const uint32 allocationFlags = HEAP_DONT_WAIT_FOR_MEMORY | HEAP_DONT_LOCK_KERNEL_SPACE; 355 356 VMArea* newArea = targetAddressSpace->CreateArea(entry->AreaName(), B_NO_LOCK, 357 protection, allocationFlags); 358 if (newArea == NULL) 359 return ENOMEM; 360 361 void* virtualAddress; 362 status_t status = targetAddressSpace->InsertArea(newArea, size, &addressRestrictions, 363 allocationFlags, &virtualAddress); 364 if (status != B_OK) 365 return EINVAL; 366 367 VMCache* cache = entry->Cache(); 368 cache->Lock(); 369 newArea->cache = cache; 370 newArea->cache_offset = 0; 371 newArea->cache_type = CACHE_TYPE_RAM; 372 373 cache->InsertAreaLocked(newArea); 374 VMAreaHash::Insert(newArea); 375 376 targetAddressSpace->Get(); 377 378 cache->AcquireRefLocked(); 379 cache->Unlock(); 380 381 idDataStructure->shm_atime = real_time_clock(); 382 idDataStructure->shm_nattch++; 383 384 *_returnAddress = virtualAddress; 385 386 return B_OK; 387 } 388 389 390 int 391 _user_xsi_shmctl(int id, int command, struct shmid_ds* _buffer) 392 { 393 status_t status; 394 395 TRACE(("shmctl: id = %d, command = %d, buffer = %p\n", id, 396 command, _buffer)); 397 398 MutexLocker _(sXsiSharedMemoryLock); 399 400 SharedMemoryEntry* entry = sSharedMemoryEntryTable.Lookup(id); 401 if (entry == NULL) 402 return EINVAL; 403 404 switch (command) { 405 case IPC_STAT: { 406 if (!entry->HasReadPermission()) 407 return EACCES; 408 409 if (!IS_USER_ADDRESS(_buffer)) 410 return B_BAD_ADDRESS; 411 412 // TODO: EOVERFLOW 413 struct shmid_ds* idDataStructure = entry->IdDataStructure(); 414 status = user_memcpy(_buffer, (const void*)idDataStructure, sizeof(struct shmid_ds)); 415 if (status != B_OK) 416 return B_BAD_ADDRESS; 417 break; 418 } 419 420 case IPC_SET: { 421 if (!entry->HasPermission()) 422 return EPERM; 423 424 if (!IS_USER_ADDRESS(_buffer)) 425 return B_BAD_ADDRESS; 426 427 struct shmid_ds* idDataStructure = entry->IdDataStructure(); 428 status = user_memcpy(idDataStructure, _buffer, sizeof(struct shmid_ds)); 429 if (status != B_OK) 430 return B_BAD_ADDRESS; 431 break; 432 } 433 434 case IPC_RMID: { 435 if (!entry->HasPermission()) 436 return EPERM; 437 438 if (entry->Key() != IPC_PRIVATE) { 439 Ipc* ipcKey = sIpcTable.Lookup(entry->Key()); 440 sIpcTable.Remove(ipcKey); 441 delete ipcKey; 442 } 443 444 sSharedMemoryEntryTable.Remove(entry); 445 atomic_add(&sSharedMemoryCount, -1); 446 447 delete entry; 448 break; 449 } 450 451 default: 452 return EINVAL; 453 } 454 455 return B_OK; 456 } 457 458 459 int 460 _user_xsi_shmdt(const void* address) 461 { 462 TRACE(("xsi_shmdt: detach address = %p\n", address)); 463 464 area_id areaId = area_for((void*)address); 465 VMArea* area = VMAreaHash::Lookup(areaId); 466 467 if (area < 0 || area == NULL) 468 return EINVAL; 469 470 MutexLocker _(sXsiSharedMemoryLock); 471 472 SharedMemoryEntry* entry; 473 SharedMemoryEntryTable::Iterator iterator = sSharedMemoryEntryTable.GetIterator(); 474 while (iterator.HasNext()) { 475 entry = iterator.Next(); 476 if (entry->Cache() == area->cache) 477 break; 478 } 479 480 status_t status = vm_delete_area(VMAddressSpace::CurrentID(), areaId, true); 481 if (status != B_OK) 482 return EINVAL; 483 484 struct shmid_ds* idDataStructure = entry->IdDataStructure(); 485 idDataStructure->shm_dtime = real_time_clock(); 486 idDataStructure->shm_nattch--; 487 488 return B_OK; 489 } 490 491 492 int 493 _user_xsi_shmget(key_t key, size_t size, int flags) 494 { 495 Ipc* ipcKey; 496 497 TRACE(("shmget: key = %d, size = %d, flags = %d\n", 498 (int)key, (int)size, flags)); 499 500 MutexLocker _(sXsiSharedMemoryLock); 501 502 if (key != IPC_PRIVATE) { 503 ipcKey = sIpcTable.Lookup(key); 504 if (ipcKey == NULL) { 505 if (!(flags & IPC_CREAT)) 506 return ENOENT; 507 508 ipcKey = new(std::nothrow) Ipc(key, size); 509 if (ipcKey == NULL) 510 return ENOMEM; 511 512 sIpcTable.Insert(ipcKey); 513 } else { 514 if ((flags & IPC_CREAT) && (flags & IPC_EXCL) != 0) 515 return EEXIST; 516 517 if ((ipcKey->Size() < size) && (size != 0)) 518 return EINVAL; 519 520 return ipcKey->SharedMemoryId(); 521 } 522 } 523 524 if (size < MIN_XSI_SHARED_MEMORY_SIZE 525 || size > MAX_XSI_SHARED_MEMORY_SIZE) 526 return EINVAL; 527 528 if (sSharedMemoryCount > MAX_XSI_SHARED_MEMORY_COUNT) 529 return ENOSPC; 530 531 SharedMemoryEntry* entry = new(std::nothrow) SharedMemoryEntry(key, size, flags); 532 if (entry == NULL) 533 return ENOMEM; 534 535 status_t status = entry->Init(); 536 if (status != B_OK) { 537 delete entry; 538 return status; 539 } 540 541 if (key != IPC_PRIVATE) 542 ipcKey->SetSharedMemoryId(entry->Id()); 543 544 sSharedMemoryEntryTable.Insert(entry); 545 546 return entry->Id(); 547 } -
src/system/kernel/syscalls.cpp
diff --git a/src/system/kernel/syscalls.cpp b/src/system/kernel/syscalls.cpp index b8efd95..4c90658 100644
a b 38 38 #include <posix/realtime_sem.h> 39 39 #include <posix/xsi_message_queue.h> 40 40 #include <posix/xsi_semaphore.h> 41 #include <posix/xsi_shared_memory.h> 41 42 #include <real_time_clock.h> 42 43 #include <safemode.h> 43 44 #include <sem.h> -
src/system/libroot/posix/sys/Jamfile
diff --git a/src/system/libroot/posix/sys/Jamfile b/src/system/libroot/posix/sys/Jamfile index 17601c8..40f0d0a 100644
a b MergeObject posix_sys.o : 26 26 wait.c 27 27 xsi_msg_queue.cpp 28 28 xsi_sem.cpp 29 xsi_shm.cpp 29 30 ; -
new file src/system/libroot/posix/sys/xsi_shm.cpp
diff --git a/src/system/libroot/posix/sys/xsi_shm.cpp b/src/system/libroot/posix/sys/xsi_shm.cpp new file mode 100644 index 0000000..67f3112
- + 1 /* 2 * Copyright 2011, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * David Höppner <0xffea@gmail.com> 7 */ 8 9 10 #include <sys/shm.h> 11 12 #include <errno.h> 13 14 #include <syscall_utils.h> 15 #include <syscalls.h> 16 17 18 void* 19 shmat(int key, const void *address, int flags) 20 { 21 void* returnAddress; 22 23 status_t status = _kern_xsi_shmat(key, address, flags, &returnAddress); 24 if (status != B_OK) { 25 errno = status; 26 return SHM_FAILED; 27 } 28 29 return returnAddress; 30 } 31 32 33 int 34 shmctl(int id, int command, struct shmid_ds *buffer) 35 { 36 RETURN_AND_SET_ERRNO(_kern_xsi_shmctl(id, command, buffer)); 37 } 38 39 40 int 41 shmdt(const void *address) 42 { 43 RETURN_AND_SET_ERRNO(_kern_xsi_shmdt(address)); 44 } 45 46 47 int 48 shmget(key_t key, size_t size, int flags) 49 { 50 RETURN_AND_SET_ERRNO(_kern_xsi_shmget(key, size, flags)); 51 } -
src/tests/system/libroot/posix/Jamfile
diff --git a/src/tests/system/libroot/posix/Jamfile b/src/tests/system/libroot/posix/Jamfile index b559251..4cce1e9 100644
a b SimpleTest init_rld_after_fork_test : init_rld_after_fork_test.cpp ; 34 34 # XSI tests 35 35 SimpleTest xsi_msg_queue_test1 : xsi_msg_queue_test1.cpp ; 36 36 SimpleTest xsi_sem_test1 : xsi_sem_test1.cpp ; 37 SimpleTest xsi_shm_test1 : xsi_shm_test1.cpp ; 37 38 38 39 # wide character tests 39 40 SimpleTest mbtest : mbtest.c ; -
new file src/tests/system/libroot/posix/xsi_shm_test1.cpp
diff --git a/src/tests/system/libroot/posix/xsi_shm_test1.cpp b/src/tests/system/libroot/posix/xsi_shm_test1.cpp new file mode 100644 index 0000000..a4c9a0b
- + 1 /* 2 * Copyright 2008-2011, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Salvatore Benedetto <salvatore.benedetto@gmail.com> 7 * David Höppner <0xffea@gmail.com> 8 */ 9 10 11 #include <errno.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 #include <sys/mman.h> 17 #include <sys/shm.h> 18 #include <sys/time.h> 19 #include <sys/wait.h> 20 #include <time.h> 21 22 #include <OS.h> 23 24 #include "TestUnitUtils.h" 25 26 27 #define KEY ((key_t)12345) 28 #define SHM_SIZE 16*1024*1024 29 30 31 static void 32 test_shmget() 33 { 34 TEST_SET("shmget({IPC_PRIVATE, key})"); 35 36 const char* currentTest = NULL; 37 38 // Open private set with IPC_PRIVATE 39 TEST("shmget(IPC_PRIVATE) - private"); 40 int shmID = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR); 41 assert_posix_bool_success(shmID != -1); 42 43 // Destroy private memory entry 44 TEST("shmctl(IPC_RMID) - private"); 45 status_t status = shmctl(shmID, IPC_RMID, NULL); 46 assert_posix_bool_success(status != -1); 47 48 // Open non-private non-existing set with IPC_CREAT 49 TEST("shmget(KEY, IPC_CREAT) non-existing"); 50 shmID = shmget(KEY, SHM_SIZE, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR 51 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 52 assert_posix_bool_success(status != -1); 53 54 // Re-open non-private existing with greater size 55 TEST("shmget(KEY) re-open existing without IPC_CREAT"); 56 int returnID = shmget(KEY, SHM_SIZE+1, 0); 57 assert_posix_bool_success(errno == EINVAL); 58 59 // Re-open non-private existing without IPC_CREAT 60 TEST("shmget(KEY) re-open existing without IPC_CREAT"); 61 returnID = shmget(KEY, SHM_SIZE, 0); 62 assert_equals(shmID, returnID); 63 64 // Re-open non-private existing with IPC_CREAT 65 TEST("shmget(IPC_CREATE) re-open existing with IPC_CREAT"); 66 returnID = shmget(KEY, SHM_SIZE, IPC_CREAT | IPC_EXCL); 67 assert_posix_bool_success(errno == EEXIST); 68 69 // Destroy non-private 70 TEST("shmctl(IPC_RMID)"); 71 status = shmctl(shmID, IPC_RMID, NULL); 72 assert_posix_bool_success(status != -1); 73 74 // Open non-private non-existing without IPC_CREAT 75 TEST("shmget(IPC_CREATE) non-existing without IPC_CREAT"); 76 shmID = shmget(KEY, SHM_SIZE, IPC_EXCL | S_IRUSR | S_IWUSR 77 | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 78 assert_posix_bool_success(errno == ENOENT); 79 80 // Destroy non-existing 81 TEST("shmctl()"); 82 status = shmctl(shmID, IPC_RMID, NULL); 83 assert_posix_bool_success(errno == EINVAL); 84 85 TEST("done"); 86 } 87 88 89 static void 90 test_shmctl() 91 { 92 TEST_SET("shmctl({IPC_STAT, IPC_SET, IPC_RMID})"); 93 94 const char* currentTest = NULL; 95 96 // Read shmid data structure for existing id 97 TEST("shmctl(ID, IPC_STAT) read shmid data structure for existing id"); 98 int shmID = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR | S_IWUSR); 99 assert_posix_bool_success(shmID != -1); 100 struct shmid_ds mds; 101 status_t status = shmctl(shmID, IPC_STAT, &mds); 102 assert_posix_bool_success(shmID != -1); 103 assert_equals(mds.shm_cpid, getpid()); 104 105 // Cache has still areas 106 TEST("shmctl(ID, IPC_RMID) remove attached id"); 107 shmat(shmID, NULL, 0); 108 shmctl(shmID, IPC_RMID, 0); 109 110 TEST("done"); 111 } 112 113 114 static void 115 test_shmdt() 116 { 117 TEST_SET("shmdt(NULL, ID)"); 118 119 const char* currentTest = NULL; 120 121 TEST("shmctl(NULL) detach NULL pointer"); 122 status_t status = shmdt(NULL); 123 assert_posix_bool_success(errno == EINVAL); 124 125 TEST("shmctl(ID) detach existing ID"); 126 int shmID = shmget(IPC_PRIVATE, SHM_SIZE, S_IRUSR); 127 void* address = shmat(shmID, NULL, 0); 128 status = shmdt(address); 129 assert_posix_bool_success(status != -1); 130 131 TEST("done"); 132 } 133 134 135 int 136 main() 137 { 138 test_shmget(); 139 test_shmdt(); 140 test_shmctl(); 141 142 printf("\nAll tests OK\n"); 143 }