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 korli, 10 years ago)

updated patch with style and build fixes

  • 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
     20typedef unsigned long shmatt_t;
     21
     22struct 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
     36void* shmat(int id, const void* address, int flags);
     37int shmctl(int id, int command, struct shmid_ds* buffer);
     38int shmdt(const void* address);
     39int 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
     19extern void xsi_shm_init();
     20
     21/* user calls */
     22status_t _user_xsi_shmat(int id, const void* address, int flags, void** _returnAddress);
     23int _user_xsi_shmctl(int id, int command, struct shmid_ds* buffer);
     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 86d407b..5afaf3a 100644
    a b struct scheduling_analysis;  
    3434struct _sem_t;
    3535struct sembuf;
    3636union semun;
     37struct shmid_ds;
    3738struct sigaction;
    3839struct signal_frame_data;
    3940struct stat;
    extern int _kern_xsi_msgsnd(int messageQueueID,  
    127128                        const void *messagePointer, size_t messageSize,
    128129                        int messageFlags);
    129130
     131/* POSIX XSI shared memory syscalls */
     132extern status_t     _kern_xsi_shmat(int id, const void* address, int flags,
     133                        void** _returnAddress);
     134extern int          _kern_xsi_shmctl(int id, int command,
     135                        struct shmid_ds* buffer);
     136extern int          _kern_xsi_shmdt(const void* address);
     137extern int          _kern_xsi_shmget(key_t key, size_t size, int flags);
     138
    130139/* team & thread syscalls */
    131140extern thread_id    _kern_load_image(const char* const* flatArgs,
    132141                        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  
    4444#include <posix/realtime_sem.h>
    4545#include <posix/xsi_message_queue.h>
    4646#include <posix/xsi_semaphore.h>
     47#include <posix/xsi_shared_memory.h>
    4748#include <real_time_clock.h>
    4849#include <sem.h>
    4950#include <smp.h>
    _start(kernel_args *bootKernelArgs, int currentCPU)  
    210211        realtime_sem_init();
    211212        xsi_sem_init();
    212213        xsi_msg_init();
     214        xsi_shm_init();
    213215
    214216        // Start a thread to finish initializing the rest of the system. Note,
    215217        // 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..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
     44static mutex sXsiSharedMemoryLock = MUTEX_INITIALIZER("Global POSIX XSI Shared Memory Lock");
     45static int32 sSharedMemoryCount = 0;
     46static int32 sGlobalSequenceNumber = 1;
     47
     48
     49class SharedMemoryEntry {
     50public:
     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
     171private:
     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
     181struct 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
     206typedef BOpenHashTable<XsiSharedMemoryEntryHashTableDefinition> SharedMemoryEntryTable;
     207static SharedMemoryEntryTable sSharedMemoryEntryTable;
     208
     209
     210class Ipc {
     211public:
     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
     245private:
     246    key_t   fKey;
     247    size_t  fSize;
     248    int fSharedMemoryId;
     249    Ipc*    fLink;
     250};
     251
     252struct 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
     277static BOpenHashTable<IpcHashTableDefinition> sIpcTable;
     278
     279
     280void
     281SharedMemoryEntry::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
     296void
     297xsi_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
     309status_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
     388int
     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
     457int
     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
     490int
     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  
    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 db2e5ed..f218b80 100644
    a b for architectureObject in [ MultiArchSubDirSetup ] {  
    3232            wait.cpp
    3333            xsi_msg_queue.cpp
    3434            xsi_sem.cpp
     35            xsi_shm.cpp
    3536            ;
    3637    }
    3738}
  • 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
     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 ((void*)-1);
     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 56396e8..0991d5f 100644
    a b SimpleTest init_rld_after_fork_test : init_rld_after_fork_test.cpp ;  
    3636# XSI tests
    3737SimpleTest xsi_msg_queue_test1 : xsi_msg_queue_test1.cpp ;
    3838SimpleTest xsi_sem_test1 : xsi_sem_test1.cpp ;
     39SimpleTest xsi_shm_test1 : xsi_shm_test1.cpp ;
    3940
    4041# wide character tests
    4142SimpleTest 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
     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}