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