Ticket #2657: draft-shm-002.patch

File draft-shm-002.patch, 22.9 KB (added by 0xffea, 13 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
     23typedef unsigned long shmatt_t;
     24
     25struct 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
     39void*   shmat(int id, const void* address, int flags);
     40int shmctl(int id, int command, struct shmid_ds* mds);
     41int shmdt(const void* address);
     42int 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
     19extern void xsi_shm_init();
     20
     21/* user calls */
     22status_t    _user_xsi_shmat(int id, const void* address, int, void** rAddress);
     23int     _user_xsi_shmctl(int id, int command, struct shmid_ds* mds);
     24int     _user_xsi_shmdt(const void* address);
     25int     _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;  
    3535struct sembuf;
    3636union semun;
    3737struct sigaction;
     38struct shmid_ds;
    3839struct stat;
    3940struct system_profiler_parameters;
    4041
    extern int _kern_xsi_msgsnd(int messageQueueID,  
    125126                        const void *messagePointer, size_t messageSize,
    126127                        int messageFlags);
    127128
     129/* POSIX XSI shared memory syscalls */
     130extern status_t     _kern_xsi_shmat(int a, const void* memoryPointer, int b, void **addr);
     131extern int      _kern_xsi_shmctl(int a, int b, struct shmid_ds *memoryDs);
     132extern int      _kern_xsi_shmdt(const void *memoryPointer);
     133extern int      _kern_xsi_shmget(key_t key, size_t size, int flags);
     134
    128135/* team & thread syscalls */
    129136extern thread_id    _kern_load_image(const char* const* flatArgs,
    130137                        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  
    4242#include <posix/realtime_sem.h>
    4343#include <posix/xsi_message_queue.h>
    4444#include <posix/xsi_semaphore.h>
     45#include <posix/xsi_shared_memory.h>
    4546#include <real_time_clock.h>
    4647#include <sem.h>
    4748#include <smp.h>
    _start(kernel_args *bootKernelArgs, int currentCPU)  
    190191        realtime_sem_init();
    191192        xsi_sem_init();
    192193        xsi_msg_init();
     194        xsi_shm_init();
    193195
    194196        // Start a thread to finish initializing the rest of the system. Note,
    195197        // 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 :  
    66    realtime_sem.cpp
    77    xsi_message_queue.cpp
    88    xsi_semaphore.cpp
     9    xsi_shared_memory.cpp
    910
    1011    : $(TARGET_KERNEL_PIC_CCFLAGS)
    1112;
  • 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
     46static mutex sXsiSharedMemoryLock = MUTEX_INITIALIZER("Global POSIX XSI Shared Memory Lock");
     47static int sSharedMemoryCount = 0;
     48static uint32 sGlobalSequenceNumber = 1;
     49
     50
     51class SharedMemoryEntry {
     52public:
     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
     173private:
     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
     183struct 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
     208typedef BOpenHashTable<XsiSharedMemoryEntryHashTableDefinition> SharedMemoryEntryTable;
     209static SharedMemoryEntryTable sSharedMemoryEntryTable;
     210
     211
     212class Ipc {
     213public:
     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
     247private:
     248    key_t   fKey;
     249    size_t  fSize;
     250    int fSharedMemoryId;
     251    Ipc*    fLink;
     252};
     253
     254struct 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
     279static BOpenHashTable<IpcHashTableDefinition> sIpcTable;
     280
     281
     282void
     283SharedMemoryEntry::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
     298void
     299xsi_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
     311status_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
     390int
     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
     459int
     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
     492int
     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  
    3838#include <posix/realtime_sem.h>
    3939#include <posix/xsi_message_queue.h>
    4040#include <posix/xsi_semaphore.h>
     41#include <posix/xsi_shared_memory.h>
    4142#include <real_time_clock.h>
    4243#include <safemode.h>
    4344#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 :  
    2626    wait.c
    2727    xsi_msg_queue.cpp
    2828    xsi_sem.cpp
     29    xsi_shm.cpp
    2930;
  • 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
     18void*
     19shmat(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
     33int
     34shmctl(int id, int command, struct shmid_ds *buffer)
     35{
     36    RETURN_AND_SET_ERRNO(_kern_xsi_shmctl(id, command, buffer));
     37}
     38
     39
     40int
     41shmdt(const void *address)
     42{
     43    RETURN_AND_SET_ERRNO(_kern_xsi_shmdt(address));
     44}
     45
     46
     47int
     48shmget(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 ;  
    3434# XSI tests
    3535SimpleTest xsi_msg_queue_test1 : xsi_msg_queue_test1.cpp ;
    3636SimpleTest xsi_sem_test1 : xsi_sem_test1.cpp ;
     37SimpleTest xsi_shm_test1 : xsi_shm_test1.cpp ;
    3738
    3839# wide character tests
    3940SimpleTest 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
     31static void
     32test_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
     89static void
     90test_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
     114static void
     115test_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
     135int
     136main()
     137{
     138    test_shmget();
     139    test_shmdt();
     140    test_shmctl();
     141
     142    printf("\nAll tests OK\n");
     143}