static int test_cnode_mint(env_t env) { int error; seL4_Word src, dest; /* A call that should succeed. */ src = get_cap(&env->vka); dest = get_free_slot(env); error = cnode_mint(env, src, dest, seL4_AllRights, seL4_NilData); test_assert(!error); test_assert(!are_tcbs_distinct(src, dest)); /* Mint to an occupied slot (should fail). */ src = get_cap(&env->vka); dest = get_cap(&env->vka); error = cnode_mint(env, src, dest, seL4_AllRights, seL4_NilData); test_assert(error == seL4_DeleteFirst); test_assert(are_tcbs_distinct(src, dest)); /* Mint from an empty slot (should fail). */ src = get_free_slot(env); dest = get_free_slot(env); error = cnode_mint(env, src, dest, seL4_AllRights, seL4_NilData); test_assert(error == seL4_FailedLookup); test_assert(are_tcbs_distinct(src, dest)); return sel4test_get_result(); }
static int test_cnode_mutate(env_t env) { int error; seL4_Word src, dest; /* A call that should succeed. */ src = get_cap(&env->vka); dest = get_free_slot(env); error = cnode_mutate(env, src, dest); test_assert(!error); test_assert(is_slot_empty(env, src)); test_assert(!is_slot_empty(env, dest)); /* Mutating to an occupied slot (should fail). */ src = get_cap(&env->vka); dest = get_cap(&env->vka); error = cnode_mutate(env, src, dest); test_assert(error == seL4_DeleteFirst); test_assert(!is_slot_empty(env, src)); test_assert(!is_slot_empty(env, dest)); /* Mutating an empty slot (should fail). */ src = get_free_slot(env); dest = get_free_slot(env); error = cnode_mutate(env, src, dest); test_assert(error == seL4_FailedLookup); test_assert(is_slot_empty(env, src)); test_assert(is_slot_empty(env, dest)); return sel4test_get_result(); }
static int test_cnode_rotate(env_t env) { int error; seL4_Word src, pivot, dest; /* A call that should succeed. */ src = get_cap(&env->vka); pivot = get_cap(&env->vka); dest = get_free_slot(env); error = cnode_rotate(env, src, pivot, dest); test_assert(!error); test_assert(is_slot_empty(env, src)); test_assert(!is_slot_empty(env, pivot)); test_assert(!is_slot_empty(env, dest)); /* Destination occupied (should fail). */ src = get_cap(&env->vka); pivot = get_cap(&env->vka); dest = get_cap(&env->vka); error = cnode_rotate(env, src, pivot, dest); test_assert(error == seL4_DeleteFirst); test_assert(!is_slot_empty(env, src)); test_assert(!is_slot_empty(env, pivot)); test_assert(!is_slot_empty(env, dest)); /* Swapping two caps (should succeed). */ src = get_cap(&env->vka); pivot = get_cap(&env->vka); dest = src; error = cnode_rotate(env, src, pivot, dest); test_assert(!error); test_assert(!are_tcbs_distinct(src, dest)); test_assert(!is_slot_empty(env, pivot)); /* Moving a cap onto itself (should fail). */ src = get_cap(&env->vka); pivot = src; dest = get_free_slot(env); error = cnode_rotate(env, src, pivot, dest); test_assert(error == seL4_IllegalOperation); test_assert(!is_slot_empty(env, src)); test_assert(is_slot_empty(env, dest)); /* Moving empty slots (should fail). */ src = get_free_slot(env); pivot = get_free_slot(env); dest = get_free_slot(env); error = cnode_rotate(env, src, pivot, dest); test_assert(error == seL4_FailedLookup); test_assert(is_slot_empty(env, src)); test_assert(is_slot_empty(env, pivot)); test_assert(is_slot_empty(env, dest)); return sel4test_get_result(); }
int digi_start_sound_object(int obj) { int slot; if (!digi_initialised) return -1; LOCK(); slot = get_free_slot(); if (slot<0) { UNLOCK(); return -1; } SoundSlots[slot].soundno = SoundObjects[obj].soundnum; SoundSlots[slot].samples = Sounddat(SoundObjects[obj].soundnum)->data; SoundSlots[slot].length = Sounddat(SoundObjects[obj].soundnum)->length; SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume); SoundSlots[slot].pan = SoundObjects[obj].pan; SoundSlots[slot].position = 0; SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER); SoundSlots[slot].playing = 1; SoundObjects[obj].signature = next_signature++; SoundObjects[obj].handle = slot; SoundObjects[obj].flags |= SOF_PLAYING; //added on 980905 by adb to add sound kill system from original sos digi.c reset_sounds_on_channel(slot); //end edit by adb UNLOCK(); return 0; }
int digi_start_sound(int soundnum, fix volume, fix pan, int unknown1, int unknown2, int unknown3, int unknown4) { int ntries; int slot; if (!digi_initialised) return -1; //added on 980905 by adb from original source to add sound kill system // play at most digi_max_channel samples, if possible kill sample with low volume ntries = 0; TryNextChannel: if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) { if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) ) { //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle )); next_handle++; if ( next_handle >= digi_max_channels ) next_handle = 0; ntries++; goto TryNextChannel; } //mprintf(( 0, "[SS:%d]", next_handle )); SoundSlots[SampleHandles[next_handle]].playing = 0; SampleHandles[next_handle] = -1; } //end edit by adb slot = get_free_slot(); if (slot<0) return -1; SoundSlots[slot].soundno = soundnum; SoundSlots[slot].samples = GameSounds[soundnum].data; SoundSlots[slot].length = GameSounds[soundnum].length; SoundSlots[slot].volume = fixmul(digi_volume, volume); SoundSlots[slot].pan = pan; SoundSlots[slot].position = 0; SoundSlots[slot].looped = 0; SoundSlots[slot].playing = 1; //added on 980905 by adb to add sound kill system from original sos digi.c reset_sounds_on_channel(slot); SampleHandles[next_handle] = slot; next_handle++; if ( next_handle >= digi_max_channels ) next_handle = 0; //end edit by adb return slot; }
int digi_start_sound(int soundnum, fix volume, fix pan) { int ntries; int slot; if (!digi_initialised) return -1; LOCK(); //added on 980905 by adb from original source to add sound kill system // play at most digi_max_channel samples, if possible kill sample with low volume ntries = 0; TryNextChannel: if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) { if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) ) { next_handle++; if ( next_handle >= digi_max_channels ) next_handle = 0; ntries++; goto TryNextChannel; } SoundSlots[SampleHandles[next_handle]].playing = 0; SampleHandles[next_handle] = -1; } //end edit by adb slot = get_free_slot(); if (slot<0) return -1; SoundSlots[slot].soundno = soundnum; SoundSlots[slot].samples = Sounddat(soundnum)->data; SoundSlots[slot].length = Sounddat(soundnum)->length; SoundSlots[slot].volume = fixmul(digi_volume, volume); SoundSlots[slot].pan = pan; SoundSlots[slot].position = 0; SoundSlots[slot].looped = 0; SoundSlots[slot].playing = 1; //added on 980905 by adb to add sound kill system from original sos digi.c reset_sounds_on_channel(slot); SampleHandles[next_handle] = slot; next_handle++; if ( next_handle >= digi_max_channels ) next_handle = 0; //end edit by adb UNLOCK(); return slot; }
static int test_cnode_delete(env_t env) { int error; seL4_Word slot; /* A call that should succeed. */ slot = get_cap(&env->vka); error = cnode_delete(env, slot); test_assert(!error); test_assert(is_slot_empty(env, slot)); /* Deleting a free slot (should succeed). */ slot = get_free_slot(env); error = cnode_delete(env, slot); test_assert(!error); test_assert(is_slot_empty(env, slot)); return sel4test_get_result(); }
static int test_cnode_revoke(env_t env) { int error; seL4_Word slot; /* A call that should succeed. */ slot = get_cap(&env->vka); error = cnode_revoke(env, slot); test_assert(!error); test_assert(!is_slot_empty(env, slot)); /* Revoking a null cap (should fail). */ slot = get_free_slot(env); error = cnode_revoke(env, slot); test_assert(!error); test_assert(is_slot_empty(env, slot)); return sel4test_get_result(); }
static int test_cnode_recycle(env_t env) { int error; seL4_Word slot; /* A call that should succeed. */ slot = get_cap(&env->vka); error = cnode_recycle(env, slot); test_assert(!error); test_assert(!is_slot_empty(env, slot)); /* Recycling an empty slot (should fail). */ slot = get_free_slot(env); error = cnode_recycle(env, slot); test_assert(error == seL4_IllegalOperation); test_assert(is_slot_empty(env, slot)); return sel4test_get_result(); }
static int test_cnode_savecaller(env_t env) { int error; seL4_Word slot; /* A call that should succeed. */ slot = get_free_slot(env); error = cnode_savecaller(env, slot); test_assert(!error); /* Save to an occupied slot (should fail). */ slot = get_cap(&env->vka); error = cnode_savecaller(env, slot); test_assert(error == seL4_DeleteFirst); test_assert(!is_slot_empty(env, slot)); /* TODO: Test saving an actual reply capability. */ return sel4test_get_result(); }
/************************************************************************ * CREATE A NEW /lost+found - INODE FOR KEEPING LOST BLOCKS * * - This procedure is called, if the checker was not able to find a * valid /lost+found - directory. * - It is assumed, that ip points to the inode of the root-directory * * Parameter : ip = Pointer to the root directory-inode * Return : TRUE : We had success by creating a new /lost+found entry * FAKSE : The attempt to create failed. * ***********************************************************************/ word create_lostfound_inode ( struct inode *ip ) { daddr_t bnr; word offset; struct buf *bip; Date date; #if DEBUG IOdebug (" create_lostfound_inode : Allocate a free slot to keep /lost+found"); #endif /* Got a free slot with success?*/ if ( get_free_slot ( ip, &bnr, &offset ) ) { /* Read the specified block. */ bip = bread ( 0, bnr, 1, SAVEA ); /* if read fails longjmp */ /* term_jmp */ /* Prepare all necessary fields */ strcpy ( bip->b_un.b_dir[offset].de_name, "lost+found" ); bip->b_un.b_dir[offset].de_inode.i_mode = Type_Directory; bip->b_un.b_dir[offset].de_inode.i_matrix = DefDirMatrix; date = GetDate(); bip->b_un.b_dir[offset].de_inode.i_ctime = date; bip->b_un.b_dir[offset].de_inode.i_mtime = date ; bip->b_un.b_dir[offset].de_inode.i_atime = date; /* Write the modified directory-*/ test_bwrite ( bip ); /* block back to disk. */ /* Modify the parent-inode */ ip->i_spare++; /* One more entry in the dir */ /* to denote. */ ip->i_size += sizeof (struct dir_elem); return TRUE; } else /* We return with the message */ return FALSE; /* that we have failed to create*/ /* a new /lost+found - inode. */ }
/** * Get the most up to date value of the given cf var. * * @param [in] var Pointer to a cf var * @param [out] res Pointer to location where the variable's value will be output * @param [out] version Pointer (may be NULL) to 64-bit integer where the current version will be output * * @return Zero on success, a system error code otherwise */ int pthread_var_get_np(pthread_var_np_t vp, void **res, uint64_t *version) { int err = 0; uint32_t slot_idx; uint32_t slots_in_use; uint64_t vers; struct slot *slot; struct value *newest; if (version == NULL) version = &vers; *version = 0; *res = NULL; if ((slot = pthread_getspecific(vp->tkey)) == NULL) { /* First time for this thread -> O(N) slow path (subscribe thread) */ slot_idx = atomic_inc_32_nv(&vp->next_slot_idx) - 1; if ((slot = get_free_slot(vp)) == NULL) { /* Slower path still: grow slots array list */ err = grow_slots(vp, slot_idx, 2); /* O(log N) */ assert(err == 0); slot = get_slot(vp, slot_idx); /* O(N) */ assert(slot != NULL); atomic_write_32(&slot->in_use, 1); } assert(slot->vp == vp); slots_in_use = atomic_inc_32_nv(&vp->slots_in_use); assert(slots_in_use > 1); if ((err = pthread_setspecific(vp->tkey, slot)) != 0) return err; } /* * Else/then fast path: one acquire read, one release write, no * free()s. O(1). * * We have to loop because we could read one value in the * conditional and that value could get freed if a writer runs * between the read in the conditional and the assignment to * slot->value with no other readers also succeeding in capturing * that value before that writer completes. * * This loop will run just once if there are no writers, and will * run as many times as writers can run between the conditional and * the body. This loop can only be an infinite loop if there's an * infinite number of writers who run with higher priority than this * thread. This is why writers yield() before dropping their write * lock. * * Note that in the body of this loop we can write a soon-to-become- * invalid value to our slot because many writers can write between * the loop condition and the body. The writer has to jump through * some hoops to deal with this. */ while (atomic_read_ptr((volatile void **)&slot->value) != (newest = atomic_read_ptr((volatile void **)&vp->values))) atomic_write_ptr((volatile void **)&slot->value, newest); if (newest != NULL) { *res = newest->value; *version = newest->version; } return 0; }
static int test_page_flush(env_t env) { seL4_CPtr frame, framec; uintptr_t vstart, vstartc; volatile uint32_t *ptr, *ptrc; vka_t *vka; int err; vka = &env->vka; void *vaddr; void *vaddrc; reservation_t reservation, reservationc; reservation = vspace_reserve_range(&env->vspace, PAGE_SIZE_4K, seL4_AllRights, 0, &vaddr); assert(reservation.res); reservationc = vspace_reserve_range(&env->vspace, PAGE_SIZE_4K, seL4_AllRights, 1, &vaddrc); assert(reservationc.res); vstart = (uintptr_t)vaddr; assert(IS_ALIGNED(vstart, seL4_PageBits)); vstartc = (uintptr_t)vaddrc; assert(IS_ALIGNED(vstartc, seL4_PageBits)); ptr = (volatile uint32_t*)vstart; ptrc = (volatile uint32_t*)vstartc; /* Create a frame */ frame = vka_alloc_frame_leaky(vka, PAGE_BITS_4K); test_assert(frame != seL4_CapNull); /* Duplicate the cap */ framec = get_free_slot(env); test_assert(framec != seL4_CapNull); err = cnode_copy(env, frame, framec, seL4_AllRights); test_assert(!err); /* map in a cap with cacheability */ err = vspace_map_pages_at_vaddr(&env->vspace, &framec, NULL, vaddrc, 1, seL4_PageBits, reservationc); test_assert(!err); /* map in a cap without cacheability */ err = vspace_map_pages_at_vaddr(&env->vspace, &frame, NULL, vaddr, 1, seL4_PageBits, reservation); test_assert(!err); /* Clean makes data observable to non-cached page */ *ptr = 0xC0FFEE; *ptrc = 0xDEADBEEF; test_assert(*ptr == 0xC0FFEE); test_assert(*ptrc == 0xDEADBEEF); err = seL4_ARM_Page_Clean_Data(framec, 0, PAGE_SIZE_4K); assert(!err); test_assert(*ptr == 0xDEADBEEF); test_assert(*ptrc == 0xDEADBEEF); /* Clean/Invalidate makes data observable to non-cached page */ *ptr = 0xC0FFEE; *ptrc = 0xDEADBEEF; test_assert(*ptr == 0xC0FFEE); test_assert(*ptrc == 0xDEADBEEF); err = seL4_ARM_Page_CleanInvalidate_Data(framec, 0, PAGE_SIZE_4K); assert(!err); test_assert(*ptr == 0xDEADBEEF); test_assert(*ptrc == 0xDEADBEEF); /* Invalidate makes RAM data observable to cached page */ *ptr = 0xC0FFEE; *ptrc = 0xDEADBEEF; test_assert(*ptr == 0xC0FFEE); test_assert(*ptrc == 0xDEADBEEF); err = seL4_ARM_Page_Invalidate_Data(framec, 0, PAGE_SIZE_4K); assert(!err); /* In case the invalidation performs an implicit clean, write a new value to RAM and make sure the cached read retrieves it Remember to drain any store buffer! */ *ptr = 0xBEEFCAFE; #ifdef CONFIG_ARCH_ARM_V7A asm volatile ("dmb" ::: "memory"); #endif test_assert(*ptrc == 0xBEEFCAFE); test_assert(*ptr == 0xBEEFCAFE); return sel4test_get_result(); }
int digi_start_sound_object(int obj) { int slot; HRESULT hr; if (!digi_initialised) return -1; slot = get_free_slot(); if (slot<0) return -1; SoundSlots[slot].soundno = SoundObjects[obj].soundnum; SoundSlots[slot].samples = Sounddat(SoundObjects[obj].soundnum)->data; SoundSlots[slot].length = Sounddat(SoundObjects[obj].soundnum)->length; SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume); SoundSlots[slot].pan = SoundObjects[obj].pan; SoundSlots[slot].position = 0; SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER); SoundSlots[slot].playing = 1; memset(&waveformat, 0, sizeof(waveformat)); waveformat.wFormatTag=WAVE_FORMAT_PCM; waveformat.wBitsPerSample = Sounddat(SoundObjects[obj].soundnum)->bits; waveformat.nChannels = 1; waveformat.nSamplesPerSec = Sounddat(SoundObjects[obj].soundnum)->freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample/8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; memset(&dsbd, 0, sizeof(dsbd)); dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME) | DSBCAPS_GETCURRENTPOSITION2; dsbd.dwReserved=0; dsbd.dwBufferBytes = SoundSlots[slot].length; dsbd.lpwfxFormat = &waveformat; hr = IDirectSound_CreateSoundBuffer(lpds, &dsbd, &SoundSlots[slot].lpsb, NULL); if ( hr != DS_OK ) { abort(); } { char *ptr1, *ptr2; DWORD len1, len2; IDirectSoundBuffer_Lock(SoundSlots[slot].lpsb, 0, SoundSlots[slot].length, (void **)&ptr1, &len1, (void **)&ptr2, &len2, 0); memcpy(ptr1, SoundSlots[slot].samples, MIN(len1,(int)SoundSlots[slot].length)); IDirectSoundBuffer_Unlock(SoundSlots[slot].lpsb, (void *)ptr1, len1, (void *)ptr2, len2); } IDirectSoundBuffer_SetPan(SoundSlots[slot].lpsb, ((int)(f2fl(SoundSlots[slot].pan) * 20000))-10000); IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb,D1vol2DSvol(SoundSlots[slot].volume)); IDirectSoundBuffer_Play(SoundSlots[slot].lpsb, 0, 0, SoundSlots[slot].looped?DSBPLAY_LOOPING:0); SoundObjects[obj].signature = next_signature++; SoundObjects[obj].handle = slot; SoundObjects[obj].flags |= SOF_PLAYING; //added on 980905 by adb to add sound kill system from original sos digi.c reset_sounds_on_channel(slot); //end edit by adb return 0; }
int digi_start_sound(int soundnum, fix volume, fix pan) { int ntries; int slot; HRESULT hr; if (!digi_initialised) return -1; //added on 980905 by adb from original source to add sound kill system // play at most digi_max_channel samples, if possible kill sample with low volume ntries = 0; TryNextChannel: if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) { if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) ) { //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle )); next_handle++; if ( next_handle >= digi_max_channels ) next_handle = 0; ntries++; goto TryNextChannel; } //mprintf(( 0, "[SS:%d]", next_handle )); DS_release_slot(SampleHandles[next_handle],1); SampleHandles[next_handle] = -1; } //end edit by adb slot = get_free_slot(); if (slot<0) return -1; SoundSlots[slot].soundno = soundnum; SoundSlots[slot].samples = Sounddat(soundnum)->data; SoundSlots[slot].length = Sounddat(soundnum)->length; SoundSlots[slot].volume = fixmul(digi_volume, volume); SoundSlots[slot].pan = pan; SoundSlots[slot].position = 0; SoundSlots[slot].looped = 0; SoundSlots[slot].playing = 1; memset(&waveformat, 0, sizeof(waveformat)); waveformat.wFormatTag=WAVE_FORMAT_PCM; waveformat.wBitsPerSample = Sounddat(soundnum)->bits; waveformat.nChannels = 1; waveformat.nSamplesPerSec = Sounddat(soundnum)->freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample/8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; memset(&dsbd, 0, sizeof(dsbd)); dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME) | DSBCAPS_GETCURRENTPOSITION2; dsbd.dwReserved=0; dsbd.dwBufferBytes = SoundSlots[slot].length; dsbd.lpwfxFormat = &waveformat; hr = IDirectSound_CreateSoundBuffer(lpds, &dsbd, &SoundSlots[slot].lpsb, NULL); if ( hr != DS_OK ) { printf("Createsoundbuffer failed! hr=0x%X\n", (int)hr); abort(); } { char *ptr1, *ptr2; DWORD len1, len2; IDirectSoundBuffer_Lock(SoundSlots[slot].lpsb, 0, Sounddat(soundnum)->length, (void **)&ptr1, &len1, (void **)&ptr2, &len2, 0); memcpy(ptr1,Sounddat(soundnum)->data, MIN((int) len1, Sounddat(soundnum)->length)); IDirectSoundBuffer_Unlock(SoundSlots[slot].lpsb, ptr1, len1, ptr2, len2); } IDirectSoundBuffer_SetPan(SoundSlots[slot].lpsb, ((int)(f2fl(pan) * 20000.0))-10000); IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb, D1vol2DSvol(SoundSlots[slot].volume)); IDirectSoundBuffer_Play(SoundSlots[slot].lpsb, 0, 0, 0); //added on 980905 by adb to add sound kill system from original sos digi.c reset_sounds_on_channel(slot); SampleHandles[next_handle] = slot; next_handle++; if ( next_handle >= digi_max_channels ) next_handle = 0; //end edit by adb return slot; }
/* RECYCLE0001 only tests if a thread gets its IPC canceled. The IPC * can succeed even if the cap it used got deleted provided the final * capability was not recycled (thus causing an IPC cancel to happen) * This means that RECYCLE0001 will pass even if all the derived badges * are deleted, since deleting them did NOT delete the final capability * or cause a recycle so outstanding IPCs were not canceled */ static int test_ep_recycle2(env_t env) { seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 0); struct { helper_thread_t thread; seL4_CPtr sync_ep; seL4_CPtr badged_ep; seL4_CPtr derived_badged_ep; volatile seL4_Word last_status; } helpers[NUM_BADGED_CLIENTS]; seL4_CPtr ep; helper_thread_t reply_thread; UNUSED int error; /* Create the main EP we are testing */ ep = vka_alloc_endpoint_leaky(&env->vka); /* spawn a thread to keep replying to any messages on main ep */ create_helper_thread(env, &reply_thread); start_helper(env, &reply_thread, bouncer_func, ep, 0, 0, 0); /* Spawn helper threads each with their own sync ep and a badged copy of the main ep */ for (int i = 0; i < NUM_BADGED_CLIENTS; i++) { helpers[i].badged_ep = get_free_slot(env); assert(helpers[i].badged_ep != 0); helpers[i].derived_badged_ep = get_free_slot(env); assert(helpers[i].derived_badged_ep != 0); helpers[i].sync_ep = vka_alloc_endpoint_leaky(&env->vka); seL4_CapData_t cap_data; cap_data = seL4_CapData_Badge_new (i + 200); error = cnode_mint(env, ep, helpers[i].badged_ep, seL4_AllRights, cap_data); assert(!error); error = cnode_copy(env, helpers[i].badged_ep, helpers[i].derived_badged_ep, seL4_AllRights); assert(!error); helpers[i].last_status = -1; create_helper_thread(env, &helpers[i].thread); start_helper(env, &helpers[i].thread, (helper_fn_t) ep_test_func, helpers[i].sync_ep, helpers[i].derived_badged_ep, (seL4_Word) &helpers[i].last_status, 0); } /* Test that every thread and endpoint is working */ for (int i = 0; i < NUM_BADGED_CLIENTS; i++) { seL4_Call(helpers[i].sync_ep, tag); } for (int i = 0; i < NUM_BADGED_CLIENTS; i++) { test_assert(helpers[i].last_status); } /* Now start recycling endpoints and make sure the correct endpoints disappear */ for (int i = 0 ; i < NUM_BADGED_CLIENTS; i++) { /* Recycle an ep */ error = cnode_recycle(env, helpers[i].badged_ep); assert(!error); /* Now run every thread */ for (int j = 0; j < NUM_BADGED_CLIENTS; j++) { seL4_Call(helpers[j].sync_ep, tag); } for (int j = 0; j < NUM_BADGED_CLIENTS; j++) { if (j <= i) { test_assert(!helpers[j].last_status); } else { test_assert(helpers[j].last_status); } } } return sel4test_get_result(); }
static int test_ep_recycle(env_t env) { seL4_MessageInfo_t tag = seL4_MessageInfo_new(0, 0, 0, 0); struct { helper_thread_t thread; seL4_CPtr badged_ep; seL4_CPtr derived_badged_ep; volatile seL4_Word done; } senders[NUM_BADGED_CLIENTS]; helper_thread_t bouncer; seL4_CPtr bounce_ep; UNUSED int error; seL4_CPtr ep; /* Create the master endpoint. */ ep = vka_alloc_endpoint_leaky(&env->vka); /* Create N badged endpoints, and derive each of them. */ for (int i = 0; i < NUM_BADGED_CLIENTS; i++) { senders[i].badged_ep = get_free_slot(env); assert(senders[i].badged_ep != 0); senders[i].derived_badged_ep = get_free_slot(env); assert(senders[i].derived_badged_ep != 0); seL4_CapData_t cap_data; cap_data = seL4_CapData_Badge_new (i + 200); error = cnode_mint(env, ep, senders[i].badged_ep, seL4_AllRights, cap_data); assert(!error); error = cnode_copy(env, senders[i].badged_ep, senders[i].derived_badged_ep, seL4_AllRights); assert(!error); create_helper_thread(env, &senders[i].thread); set_helper_priority(&senders[i].thread, 100); senders[i].done = -1; } /* Create a bounce thread so we can get lower prio threads to run. */ bounce_ep = vka_alloc_endpoint_leaky(&env->vka); create_helper_thread(env, &bouncer); set_helper_priority(&bouncer, 0); start_helper(env, &bouncer, bouncer_func, bounce_ep, 0, 0, 0); for (int i = 0; i < NUM_BADGED_CLIENTS; i++) { start_helper(env, &senders[i].thread, (helper_fn_t) call_func, senders[i].derived_badged_ep, i + 100, (seL4_Word) &senders[i].done, 0); } /* Let the sender threads run. */ seL4_Call(bounce_ep, tag); /* Receive a message from each endpoint and check the badge. */ for (int i = 0; i < NUM_BADGED_CLIENTS; i++) { seL4_Word sender_badge; seL4_MessageInfo_ptr_set_length(&tag, 1); tag = seL4_Recv(ep, &sender_badge); assert(seL4_MessageInfo_get_length(tag) == 1); assert(seL4_GetMR(0) == sender_badge - 100); seL4_SetMR(0, ~seL4_GetMR(0)); seL4_Reply(tag); } /* Let the sender threads run. */ seL4_Call(bounce_ep, tag); /* Check none of the threads have failed yet. */ for (int i = 0; i < NUM_BADGED_CLIENTS; i++) { assert(senders[i].done == 0); } /* Recycle each endpoint. */ for (int i = 0; i < NUM_BADGED_CLIENTS; i++) { error = cnode_recycle(env, senders[i].badged_ep); assert(!error); /* Let thread run. */ seL4_Call(bounce_ep, tag); /* Check that only the intended threads have now aborted. */ for (int j = 0; j < NUM_BADGED_CLIENTS; j++) { if (j <= i) { assert(senders[j].done == 1); } else { assert(senders[j].done == 0); } } } seL4_Call(bounce_ep, tag); for (int i = 0; i < NUM_BADGED_CLIENTS; i++) { cleanup_helper(env, &senders[i].thread); } cleanup_helper(env, &bouncer); return sel4test_get_result(); }