docs: mark Phase 6 complete in phase6-scheduler-integration-plan
This commit is contained in:
parent
9b0e9571d1
commit
177cf45af5
17 changed files with 4226 additions and 361 deletions
|
|
@ -1,3 +1,4 @@
|
|||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -6,6 +7,147 @@
|
|||
#include "utils.h"
|
||||
#include "xstring.h"
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Concurrent-test helpers */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
#define NTHREADS (8)
|
||||
|
||||
/* Thread argument for the same-key test */
|
||||
typedef struct {
|
||||
const char* key;
|
||||
char* result;
|
||||
} same_key_arg_t;
|
||||
|
||||
static void* thread_make_same_key(void* arg)
|
||||
{
|
||||
same_key_arg_t* a = (same_key_arg_t*)arg;
|
||||
a->result = makeString((char*)a->key);
|
||||
return a->result;
|
||||
}
|
||||
|
||||
/* Thread argument for the distinct-key test */
|
||||
typedef struct {
|
||||
char key[16];
|
||||
char* result;
|
||||
} distinct_key_arg_t;
|
||||
|
||||
static void* thread_make_distinct_key(void* arg)
|
||||
{
|
||||
distinct_key_arg_t* a = (distinct_key_arg_t*)arg;
|
||||
a->result = makeString(a->key);
|
||||
return a->result;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Concurrent tests */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
* test_xstring_concurrent_same_key
|
||||
*
|
||||
* Spawn NTHREADS threads, each racing to intern the same key.
|
||||
* With the TOCTOU fix the lock is held from key_find through key_add,
|
||||
* so every thread must receive the identical interned pointer.
|
||||
* Without the fix, two threads could both miss key_find, both call
|
||||
* makeInstance, and one would leak — and the pointers would differ.
|
||||
*/
|
||||
static void test_xstring_concurrent_same_key(void)
|
||||
{
|
||||
pthread_t tids[NTHREADS];
|
||||
same_key_arg_t args[NTHREADS];
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
rc = xstring_table_init(139);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
args[i].key = "concurrent_key";
|
||||
args[i].result = NULL;
|
||||
rc = pthread_create(&tids[i], NULL, thread_make_same_key, &args[i]);
|
||||
TEST_ASSERT_TRUE(rc == 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
void* retval = NULL;
|
||||
rc = pthread_join(tids[i], &retval);
|
||||
TEST_ASSERT_TRUE(rc == 0);
|
||||
}
|
||||
|
||||
/* All threads must have received a non-NULL pointer */
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
TEST_ASSERT_TRUE(args[i].result != NULL);
|
||||
}
|
||||
|
||||
/* All pointers must be the same interned object */
|
||||
for (i = 1; i < NTHREADS; i++) {
|
||||
TEST_ASSERT_EQUAL_PTR(args[0].result, args[i].result);
|
||||
}
|
||||
|
||||
/*
|
||||
* makeString increments the refcount on a cache hit. Each thread
|
||||
* got one reference; drop NTHREADS - 1 extras so xstring_table_fini
|
||||
* can release the final one cleanly.
|
||||
*/
|
||||
for (i = 1; i < NTHREADS; i++) {
|
||||
dereference((var)args[i].result);
|
||||
}
|
||||
|
||||
xstring_table_fini();
|
||||
}
|
||||
|
||||
/*
|
||||
* test_xstring_concurrent_distinct_keys
|
||||
*
|
||||
* Spawn NTHREADS threads, each interning a unique key.
|
||||
* Every returned pointer must be non-NULL and distinct from all others,
|
||||
* confirming that concurrent inserts of different keys do not collide.
|
||||
*/
|
||||
static void test_xstring_concurrent_distinct_keys(void)
|
||||
{
|
||||
pthread_t tids[NTHREADS];
|
||||
distinct_key_arg_t args[NTHREADS];
|
||||
int rc;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
rc = xstring_table_init(139);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
snprintf(args[i].key, sizeof(args[i].key), "key_%d", i);
|
||||
args[i].result = NULL;
|
||||
rc = pthread_create(&tids[i], NULL, thread_make_distinct_key, &args[i]);
|
||||
TEST_ASSERT_TRUE(rc == 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
void* retval = NULL;
|
||||
rc = pthread_join(tids[i], &retval);
|
||||
TEST_ASSERT_TRUE(rc == 0);
|
||||
}
|
||||
|
||||
/* Every pointer must be non-NULL */
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
TEST_ASSERT_TRUE(args[i].result != NULL);
|
||||
}
|
||||
|
||||
/* Every pointer must be distinct from all others */
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
for (j = i + 1; j < NTHREADS; j++) {
|
||||
TEST_ASSERT_NOT_EQUAL(args[i].result, args[j].result);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release each thread's reference */
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
dereference((var)args[i].result);
|
||||
}
|
||||
|
||||
xstring_table_fini();
|
||||
}
|
||||
|
||||
static void test_xstring_create(void)
|
||||
{
|
||||
char* s = "Hello, world";
|
||||
|
|
@ -76,6 +218,8 @@ void test_xstrings(void)
|
|||
RUN_TEST(test_xstring_create);
|
||||
RUN_TEST(test_xstring_deref);
|
||||
RUN_TEST(test_xstring_share);
|
||||
RUN_TEST(test_xstring_concurrent_same_key);
|
||||
RUN_TEST(test_xstring_concurrent_distinct_keys);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue