diff --git a/linux/devdoc/threadpool_linux_requirements.md b/linux/devdoc/threadpool_linux_requirements.md index 02886fd8..f79071e1 100644 --- a/linux/devdoc/threadpool_linux_requirements.md +++ b/linux/devdoc/threadpool_linux_requirements.md @@ -9,20 +9,19 @@ `threadpool_linux` provides the Linux implementation of the `threadpool` PAL API. The `threadpool` object starts a predefined number of threads that are used to execute the work items. The `threadpool` unit tracks all the work items which need to be executed in an task array. All incoming tasks are being added in `threadpool_schedule_work` and scheduled in `threadpool_work_func`. `threadpool_linux` maintains the following: -1. `sm`: a SM handle to manage the state for `threadpool`. -2. `max_thread_count`, `min_thread_count`, `used_thread_count` : static 32-bit counters for the `threadpool` thread limits. -3. `semaphore` : a semaphore to ensure the number of waiting tasks changed atomically when a task is inserted or consumed in the array. -4. `task_array` : a circular array of waiting tasks with default size 2048, initialized in `threadpool_create`. Insert index and consume index for the array is initialized to 0. Insert index is incremented every time when a new work item add to the array, and the consume index is incremented every time when a task gets executed. The insert index modulo the array size gives the actual insert position, and the consume index modulo the array size gives the actual consume position. Each array item contains a `THREADPOOL_TASK` object, which obtains the `task_state` and task function information. +1. `max_thread_count`, `min_thread_count`, `used_thread_count` : static 32-bit counters for the `threadpool` thread limits. +2. `semaphore` : a semaphore to ensure the number of waiting tasks changed atomically when a task is inserted or consumed in the array. +3. `task_array` : a circular array of waiting tasks with default size 2048, initialized in `threadpool_create`. Insert index and consume index for the array is initialized to 0. Insert index is incremented every time when a new work item add to the array, and the consume index is incremented every time when a task gets executed. The insert index modulo the array size gives the actual insert position, and the consume index modulo the array size gives the actual consume position. Each array item contains a `THREADPOOL_TASK` object, which obtains the `task_state` and task function information. - `task_state` can be following: - `TASK_NOT_USED` : Entry is not used. Entered after a call to `threadpool_create`, new array items after a call to `reallocate_threadpool_array`, and a call to `threadpool_work_func`. - `TASK_INITIALIZING` : Start copying work item into the entry. Entered in the progress of a call to `threadpool_schedule_work`. - `TASK_WAITING` : Work item in the entry is waiting to be executed. Entered after a call to `threadpool_schedule_work` with a zero return value. - `TASK_WORKING` : Work item is executing. Entered in the progress of a call to `threadpool_work_func` by calling `threadpool_open`. -5. `task_array_size` : a 32 bit variable represents the size of the task array. -6. `insert_idx` : a 64 bit variable represents the next available insert position in the circular task array. -7. `consume_idx` : a 64 bit variable represents the next available consume position in the circular task array. -8. `srw_lock` : a SRW lock to ensure the progress of resize array will not be interupted as well as task array insert and consume get locked when task array resize happens. -9. `thread_handle_array` : an array of threads in the `threadpool`, all intialized in `threadpool_open`. +4. `task_array_size` : a 32 bit variable represents the size of the task array. +5. `insert_idx` : a 64 bit variable represents the next available insert position in the circular task array. +6. `consume_idx` : a 64 bit variable represents the next available consume position in the circular task array. +7. `srw_lock` : a SRW lock to ensure the progress of resize array will not be interupted as well as task array insert and consume get locked when task array resize happens. +8. `thread_handle_array` : an array of threads in the `threadpool`, all intialized in `threadpool_open`. ### Reallocating the Task Array @@ -113,8 +112,6 @@ MOCKABLE_FUNCTION(, THANDLE(THREADPOOL), threadpool_create, EXECUTION_ENGINE_HAN **SRS_THREADPOOL_LINUX_07_002: [** If `execution_engine` is `NULL`, `threadpool_create` shall fail and return `NULL`. **]** -**SRS_THREADPOOL_LINUX_07_003: [** `threadpool_create` shall create a `SM_HANDLE` by calling `sm_create`. **]** - **SRS_THREADPOOL_LINUX_07_004: [** `threadpool_create` shall get the `min_thread_count` and `max_thread_count` thread parameters from the `execution_engine`. **]** **SRS_THREADPOOL_LINUX_07_005: [** `threadpool_create` shall allocate memory for an array of thread handles of size `min_thread_count` and on success return a non-`NULL` handle to it. **]** @@ -129,9 +126,9 @@ MOCKABLE_FUNCTION(, THANDLE(THREADPOOL), threadpool_create, EXECUTION_ENGINE_HAN **SRS_THREADPOOL_LINUX_07_010: [** `insert_idx` and `consume_idx` for the task array shall be initialized to 0. **]** -**S_R_S_THREADPOOL_LINUX_07_020: [** `threadpool_create` shall create `min_thread_count` number of threads for `threadpool` using `ThreadAPI_Create`. **]** +**SRS_THREADPOOL_LINUX_07_020: [** `threadpool_create` shall create `min_thread_count` number of threads for `threadpool` using `ThreadAPI_Create`. **]** -**S_R_S_THREADPOOL_LINUX_07_022: [** If one of the thread creation fails, `threadpool_create` shall fail and return a non-zero value, terminate all threads already created. **]** +**SRS_THREADPOOL_LINUX_07_022: [** If one of the thread creation fails, `threadpool_create` shall fail and return a non-zero value, terminate all threads already created. **]** **SRS_THREADPOOL_LINUX_07_011: [** If any error occurs, `threadpool_create` shall fail and return `NULL`. **]** @@ -143,16 +140,14 @@ static void threadpool_dispose(THREADPOOL* threadpool) `threadpool_dispose` frees the resouces associated with threadpool. -**SRS_THREADPOOL_LINUX_07_013: [** `threadpool_dispose` shall perform an implicit close if `threadpool` is open. **]** +**SRS_THREADPOOL_LINUX_07_089: [** `threadpool_dispose` shall signal all threads to return. **]** + +**SRS_THREADPOOL_LINUX_07_027: [** `threadpool_dispose` shall join all threads in the `threadpool`. **]** **SRS_THREADPOOL_LINUX_07_014: [** `threadpool_dispose` shall destroy the semphore by calling `sem_destroy`. **]** **SRS_THREADPOOL_LINUX_07_015: [** `threadpool_dispose` shall destroy the SRW lock by calling `srw_lock_destroy`. **]** -**S_R_S_THREADPOOL_LINUX_07_089: [** `threadpool_dispose` shall signal all the threads that `threadpool` is closing by calling `InterlockedHL_SetAndWakeAll`. **]** - -**S_R_S_THREADPOOL_LINUX_07_027: [** `threadpool_dispose` shall join all threads in the `threadpool`. **]** - **SRS_THREADPOOL_LINUX_07_016: [** `threadpool_dispose` shall free the memory allocated in `threadpool_create`. **]** ### threadpool_open @@ -165,40 +160,18 @@ Note: `threadpool_open` will be deprecated and `threadpool_create` will perform **SRS_THREADPOOL_LINUX_07_017: [** If `threadpool` is `NULL`, `threadpool_open` shall fail and return a non-zero value. **]** -**SRS_THREADPOOL_LINUX_07_018: [** `threadpool_open` shall call `sm_open_begin`. **]** - -**SRS_THREADPOOL_LINUX_07_019: [** If `sm_open_begin` indicates the open cannot be performed, `threadpool_open` shall fail and return a non-zero value. **]** - -**SRS_THREADPOOL_LINUX_11_001: [** `threadpool_open` shall initialize internal threapool data items **]** - -**SRS_THREADPOOL_LINUX_07_020: [** `threadpool_open` shall create `min_thread_count` number of threads for `threadpool` using `ThreadAPI_Create`. **]** - -**SRS_THREADPOOL_LINUX_07_021: [** If any error occurs, `threadpool_open` shall fail and return a non-zero value. **]** - -**SRS_THREADPOOL_LINUX_07_022: [** If one of the thread creation fails, `threadpool_open` shall fail and return a non-zero value, terminate all threads already created. **]** - -**SRS_THREADPOOL_LINUX_07_023: [** Otherwise, `threadpool_open` shall shall call `sm_open_end` with true for success. **]** - -**SRS_THREADPOOL_LINUX_07_024: [** `threadpool_open` shall return zero. **]** +**SRS_THREADPOOL_LINUX_07_024: [** Otherwise, `threadpool_open` shall succeed and return 0. **]** ### threadpool_close ```C MOCKABLE_FUNCTION(, void, threadpool_close, THANDLE(THREADPOOL), threadpool); ``` -Note: `threadpool_close` will be deprecated and threadpool_dispose will perform additional tasks of threadpool_close. This function will exist until all the libraries calling this API are modified to use only `threadpool_create`. +Note: `threadpool_close` will be deprecated and `threadpool_dispose` will perform additional tasks of `threadpool_close`. This function will exist until all the libraries calling this API are modified to use only `threadpool_create`. `threadpool_close` closes the threadpool. **SRS_THREADPOOL_LINUX_07_025: [** If `threadpool` is `NULL`, `threadpool_close` shall fail and return. **]** -**SRS_THREADPOOL_LINUX_07_026: [** Otherwise, `threadpool_close` shall call `sm_close_begin`. **]** - -**SRS_THREADPOOL_LINUX_07_089: [** `threadpool_close` shall signal all threads `threadpool` is closing by calling `InterlockedHL_SetAndWakeAll`. **]** - -**SRS_THREADPOOL_LINUX_07_027: [** `threadpool_close` shall join all threads in the `threadpool`. **]** - -**SRS_THREADPOOL_LINUX_07_028: [** `threadpool_close` shall call `sm_close_end`. **]** - ### threadpool_schedule_work ```C @@ -211,10 +184,6 @@ MOCKABLE_FUNCTION(, int, threadpool_schedule_work, THANDLE(THREADPOOL), threadpo **SRS_THREADPOOL_LINUX_07_030: [** If `work_function` is `NULL`, `threadpool_schedule_work` shall fail and return a non-zero value. **]** -**SRS_THREADPOOL_LINUX_07_031: [** `threadpool_schedule_work` shall call `sm_exec_begin`. **]** - -**SRS_THREADPOOL_LINUX_07_032: [** If `sm_exec_begin` returns `SM_EXEC_REFUSED`, `threadpool_schedule_work` shall fail and return a non-zero value. **]** - **SRS_THREADPOOL_LINUX_07_033: [** `threadpool_schedule_work` shall acquire the SRW lock in shared mode by calling `srw_lock_acquire_shared`. **]** **SRS_THREADPOOL_LINUX_07_034: [** `threadpool_schedule_work` shall increment the `insert_pos`. **]** @@ -245,14 +214,12 @@ MOCKABLE_FUNCTION(, int, threadpool_schedule_work, THANDLE(THREADPOOL), threadpo **SRS_THREADPOOL_LINUX_07_048: [** If reallocating the task array fails, `threadpool_schedule_work` shall fail and return a non-zero value. **]** -**SRS_THREADPOOL_LINUX_07_049: [** `threadpool_schedule_work` shall initialize `pending_work_item_count_ptr` with `NULL` then copy the work function and work function context into insert position in the task array and assign `0` to the return variable to indicate success. **]** +**SRS_THREADPOOL_LINUX_07_049: [** `threadpool_schedule_work` shall copy the work function and work function context into insert position in the task array and assign `0` to the return variable to indicate success. **]** **SRS_THREADPOOL_LINUX_07_050: [** `threadpool_schedule_work` shall set the `task_state` to `TASK_WAITING` and then release the shared SRW lock. **]** **SRS_THREADPOOL_LINUX_07_051: [** `threadpool_schedule_work` shall unblock the `threadpool` semaphore by calling `sem_post`. **]** -**SRS_THREADPOOL_LINUX_07_053: [** `threadpool_schedule_work` shall call `sm_exec_end`. **]** - **SRS_THREADPOOL_LINUX_07_047: [** `threadpool_schedule_work` shall return zero on success. **]** ### threadpool_timer_start @@ -394,23 +361,7 @@ static int threadpool_work_func(void* param); **SRS_THREADPOOL_LINUX_07_084: [** If the work item function is not `NULL`, `threadpool_work_func` shall execute it with `work_function_ctx`. **]** -- **SRS_THREADPOOL_LINUX_05_039: [** `threadpool_work_func` shall acquire the shared `SRW lock` by calling `srw_lock_acquire_shared`. **]** - -- **SRS_THREADPOOL_LINUX_05_040: [** `threadpool_work_func` shall save `pending_work_item_count_ptr` is not `NULL` in `is_pending_work_item_count_ptr_not_null`. **]** - -- **SRS_THREADPOOL_LINUX_05_041: [** `threadpool_work_func` shall release the shared `SRW lock` by calling `srw_lock_release_shared`. **]** - -- **SRS_THREADPOOL_LINUX_05_042: [** If the `is_pending_work_item_count_ptr_not_null` is `TRUE` then: **]** - - - **SRS_THREADPOOL_LINUX_05_043: [** `threadpool_work_func` shall acquire the exclusive `SRW lock` by calling `srw_lock_acquire_exclusive`. **]** - - - **SRS_THREADPOOL_LINUX_05_044: [** `threadpool_work_func` shall decrement the `pending_work_item_count_ptr` by calling `interlocked_decrement`. **]** - - - **SRS_THREADPOOL_LINUX_05_045: [** `threadpool_work_func` shall send wake up signal to single listener for the address in `pending_work_item_count_ptr`. **]** - - - **SRS_THREADPOOL_LINUX_05_046: [** `threadpool_work_func` shall release the shared `SRW lock` by calling `srw_lock_release_exclusive`. **]** - -**SRS_THREADPOOL_LINUX_07_085: [** `threadpool_work_func` shall loop until `threadpool_close` or `threadpool_destroy` is called. **]** +**SRS_THREADPOOL_LINUX_07_085: [** `threadpool_work_func` shall loop until the flag to stop the threads is not set to 1. **]** ### threadpool_create_work_item @@ -420,24 +371,15 @@ MOCKABLE_FUNCTION(, THREADPOOL_WORK_ITEM_HANDLE, threadpool_create_work_item, TH `threadpool_create_work_item` creates a work item to be executed by the threadpool. -**SRS_THREADPOOL_LINUX_05_001: [** If `threadpool` is `NULL`, `threadpool_create_work_item` shall fail and set the return variable `threadpool_work_item` a `NULL` value. **]** +**SRS_THREADPOOL_LINUX_05_001: [** If `threadpool` is `NULL`, `threadpool_create_work_item` shall fail and return a `NULL` value. **]** -**SRS_THREADPOOL_LINUX_05_002: [** If `work_function` is `NULL`, `threadpool_create_work_item` shall fail and set the return variable `threadpool_work_item` a `NULL` value. **]** - -**SRS_THREADPOOL_LINUX_05_003: [** `threadpool_create_work_item` shall call `sm_exec_begin`. **]** - -**SRS_THREADPOOL_LINUX_05_004: [** If `sm_exec_begin` returns `SM_EXEC_REFUSED`, `threadpool_create_work_item` shall fail and set the return variable `threadpool_work_item` a `NULL` value. **]** +**SRS_THREADPOOL_LINUX_05_002: [** If `work_function` is `NULL`, `threadpool_create_work_item` shall fail and return a `NULL` value. **]** **SRS_THREADPOOL_LINUX_05_005: [** `threadpool_create_work_item` shall allocate memory for `threadpool_work_item` of type `THREADPOOL_WORK_ITEM_HANDLE`. **]** -**SRS_THREADPOOL_LINUX_05_006: [** If during the initialization of `threadpool_work_item`, `malloc` fails then `threadpool_create_work_item` shall `fail`. **]** - -**SRS_THREADPOOL_LINUX_05_007: [** `threadpool_create_work_item` shall initialize `pending_work_item_count` to `0` then copy the `work_function` and `work_function_context` into the `threadpool_work_item`. An initialized `threadpool_work_item` when returned indicates `success`. **]** - -**SRS_THREADPOOL_LINUX_05_008: [** `threadpool_create_work_item` shall call `sm_exec_end`. **]** - -**SRS_THREADPOOL_LINUX_05_009: [** Return the value inside `threadpool_work_item` **]** +**SRS_THREADPOOL_LINUX_05_006: [** If during the initialization of `threadpool_work_item`, `malloc` fails then `threadpool_create_work_item` shall fail and return a `NULL` value. **]** +**SRS_THREADPOOL_LINUX_05_007: [** `threadpool_create_work_item` shall copy the `work_function` and `work_function_context` into the threadpool work item. **]** ### threadpool_schedule_work_item @@ -447,14 +389,10 @@ MOCKABLE_FUNCTION(, int, threadpool_schedule_work_item, THANDLE(THREADPOOL), thr `threadpool_schedule_work_item` schedules a work item to be executed by the threadpool. -**SRS_THREADPOOL_LINUX_05_010: [** If `threadpool` is `NULL`, `threadpool_schedule_work_item` shall fail and set the return variable with a non-zero value. **]** +**SRS_THREADPOOL_LINUX_05_010: [** If `threadpool` is `NULL`, `threadpool_schedule_work_item` shall fail and return a non-zero value. **]** **SRS_THREADPOOL_LINUX_05_011: [** If `threadpool_work_item` is `NULL`, `threadpool_schedule_work_item` shall fail and set the return variable with a non-zero value. **]** -**SRS_THREADPOOL_LINUX_05_012: [** `threadpool_schedule_work_item` shall call `sm_exec_begin`. **]** - -**SRS_THREADPOOL_LINUX_05_013: [** If `sm_exec_begin` returns `SM_EXEC_REFUSED`, `threadpool_schedule_work_item` shall fail and set the return variable a non-zero value. **]** - **SRS_THREADPOOL_LINUX_05_014: [** `threadpool_schedule_work_item` shall acquire the `SRW lock` in shared mode by calling `srw_lock_acquire_shared`. **]** **SRS_THREADPOOL_LINUX_05_015: [** `threadpool_schedule_work_item` shall increment the `insert_pos`. **]** @@ -465,25 +403,17 @@ MOCKABLE_FUNCTION(, int, threadpool_schedule_work_item, THANDLE(THREADPOOL), thr **SRS_THREADPOOL_LINUX_05_018: [** If the previous task state is not `TASK_NOT_USED` then `threadpool_schedule_work_item` shall increase `task_array` capacity **]** -- **SRS_THREADPOOL_LINUX_05_019: [** If reallocating the task array fails, `threadpool_schedule_work_item` shall fail by setting the return variable a non-zero value and break. **]** +- **SRS_THREADPOOL_LINUX_05_019: [** If reallocating the task array fails, `threadpool_schedule_work_item` shall fail and return a non-zero value. **]** -- **SRS_THREADPOOL_LINUX_05_020: [ Otherwise, `threadpool_schedule_work_item` shall acquire the SRW lock in exclusive mode by calling srw_lock_acquire_exclusive. ]*/ +- **SRS_THREADPOOL_LINUX_05_020: [** Otherwise, `threadpool_schedule_work_item` shall acquire the SRW lock in shared mode by calling srw_lock_acquire_exclusive. **]** -- **SRS_THREADPOOL_LINUX_05_021: [** `threadpool_schedule_work_item` shall increment the `pending_work_item_count` by calling `interlocked_increment` and copy its address to `pending_work_item_count_ptr` into insert position in the task array. **]** - - **SRS_THREADPOOL_LINUX_05_022: [** `threadpool_schedule_work_item` shall copy the `work_function` and `work_function_context` from `threadpool_work_item` into insert position in the task array. **]** -- **SRS_THREADPOOL_LINUX_05_023: [** `threadpool_schedule_work_item` shall set the `task_state` to `TASK_WAITING` and then release the exclusive SRW lock by calling srw_lock_release_exclusive. **]** - -- **SRS_THREADPOOL_LINUX_05_024: [** `threadpool_schedule_work_item` shall notify a single thread that is waiting for update of this value by a wake signal. **]** +- **SRS_THREADPOOL_LINUX_05_023: [** `threadpool_schedule_work_item` shall set the `task_state` to `TASK_WAITING` and then release the shared SRW lock by calling srw_lock_release_exclusive. **]** - **SRS_THREADPOOL_LINUX_05_025: [** `threadpool_schedule_work_item` shall unblock the `threadpool` semaphore by calling `sem_post`. **]** -- **SRS_THREADPOOL_LINUX_05_026: [** `threadpool_schedule_work_item` shall set the return variable to `0` to indicate success. **]** - -**SRS_THREADPOOL_LINUX_05_027: [** `threadpool_schedule_work_item` shall call `sm_exec_end`. **]** - -**SRS_THREADPOOL_LINUX_05_028: [** `threadpool_schedule_work_item` shall return with the contents of the value of the return variable. **]** +- **SRS_THREADPOOL_LINUX_05_026: [** `threadpool_schedule_work_item` shall succeed and return 0. **]** ### threadpool_destroy_work_item @@ -497,18 +427,8 @@ MOCKABLE_FUNCTION(, void, threadpool_destroy_work_item, THANDLE(THREADPOOL), thr **SRS_THREADPOOL_LINUX_05_030: [** If `threadpool_work_item` is `NULL`, `threadpool_destroy_work_item` shall fail. **]** -**SRS_THREADPOOL_LINUX_05_031: [** `threadpool_destroy_work_item` shall call `sm_exec_begin`. **]** - -- **SRS_THREADPOOL_LINUX_05_032: [** If `sm_exec_begin` returns `SM_EXEC_REFUSED`, `threadpool_destroy_work_item` shall fail. **]** - -- **SRS_THREADPOOL_LINUX_05_033: [** Otherwise, `threadpool_destroy_work_item` shall wait for `pending_work_item_count` to become `0`. **]** - - - **SRS_THREADPOOL_LINUX_05_034: [** When `pending_work_item_count` becomes 0, `threadpool_destroy_work_item` shall acquire the `SRW lock` in shared mode by calling `srw_lock_acquire_shared`. **]** +**SRS_THREADPOOL_LINUX_05_033: [** `threadpool_destroy_work_item` shall wait for all pending work items to finish execution. **]** - **SRS_THREADPOOL_LINUX_05_035: [** `threadpool_destroy_work_item` shall free the memory allocated to the work item of type `THREADPOOL_WORK_ITEM_HANDLE` created in `threadpool_create_work_item`. **]** - - **SRS_THREADPOOL_LINUX_05_036: [** `threadpool_destroy_work_item` shall release the shared `SRW lock`. **]** - - - **SRS_THREADPOOL_LINUX_05_037: [** If `InterlockedHL_WaitForValue` does not return `INTERLOCKED_HL_OK` then Log Message with severity `CRITICAL` and `terminate`. **]** - -**SRS_THREADPOOL_LINUX_05_038: [** `threadpool_destroy_work_item` shall call `sm_exec_end`. **]** \ No newline at end of file + - **SRS_THREADPOOL_LINUX_05_037: [** If `InterlockedHL_WaitForValue` does not return `INTERLOCKED_HL_OK` then Log Message with severity `CRITICAL` and `terminate`. **]** \ No newline at end of file diff --git a/linux/src/threadpool_linux.c b/linux/src/threadpool_linux.c index cc519149..607c3a71 100644 --- a/linux/src/threadpool_linux.c +++ b/linux/src/threadpool_linux.c @@ -29,7 +29,6 @@ #include "c_pal/srw_lock.h" #include "c_pal/execution_engine.h" #include "c_pal/execution_engine_linux.h" -#include "c_pal/sm.h" #include "c_pal/log_critical_and_terminate.h" #include "c_pal/sync.h" #include "c_pal/thandle.h" // IWYU pragma: keep @@ -84,7 +83,7 @@ typedef struct THREADPOOL_WORK_ITEM_TAG typedef struct THREADPOOL_TAG { - volatile_atomic int32_t run_thread; + volatile_atomic int32_t stop_thread; uint32_t max_thread_count; uint32_t min_thread_count; int32_t used_thread_count; @@ -92,8 +91,7 @@ typedef struct THREADPOOL_TAG sem_t semaphore; SRW_LOCK_HANDLE srw_lock; - uint32_t list_index; - SM_HANDLE sm; + uint32_t list_index; THREADPOOL_TASK* task_array; volatile_atomic int32_t task_array_size; @@ -131,27 +129,6 @@ static void on_timer_callback(sigval_t timer_data) } } -static void internal_close(THREADPOOL* threadpool) -{ - /* Codes_SRS_THREADPOOL_LINUX_07_026: [ Otherwise, threadpool_close shall call sm_close_begin. ]*/ - if(sm_close_begin(threadpool->sm) == SM_EXEC_GRANTED) - { - /* Codes_SRS_THREADPOOL_LINUX_07_089: [ threadpool_close shall signal all threads threadpool is closing by calling InterlockedHL_SetAndWakeAll. ]*/ - (void)InterlockedHL_SetAndWakeAll(&threadpool->run_thread, 1); - for (int32_t index = 0; index < threadpool->used_thread_count; index++) - { - int dont_care; - /* Codes_SRS_THREADPOOL_LINUX_07_027: [ threadpool_close shall join all threads in the threadpool. ]*/ - if (ThreadAPI_Join(threadpool->thread_handle_array[index], &dont_care) != THREADAPI_OK) - { - LogError("Failure joining thread number %" PRId32 "", index); - } - } - /* Codes_SRS_THREADPOOL_LINUX_07_028: [ threadpool_close shall call sm_close_end. ]*/ - sm_close_end(threadpool->sm); - } -} - static int threadpool_work_func(void* param) { if (param == NULL) @@ -217,29 +194,21 @@ static int threadpool_work_func(void* param) if (work_function != NULL) { work_function(work_function_ctx); - /* Codes_SRS_THREADPOOL_LINUX_05_039: [ threadpool_work_func shall acquire the shared SRW lock by calling srw_lock_acquire_shared. ]*/ - srw_lock_acquire_shared(threadpool->srw_lock); - /* Codes_SRS_THREADPOOL_LINUX_05_040: [ threadpool_work_func shall save pending_work_item_count_ptr is not NULL in is_pending_work_item_count_ptr_not_null. ]*/ - bool is_pending_work_item_count_ptr_not_null = (NULL != threadpool->task_array[current_index].pending_work_item_count_ptr); - /* Codes_SRS_THREADPOOL_LINUX_05_041: [ threadpool_work_func shall release the shared SRW lock by calling srw_lock_release_shared. ]*/ - srw_lock_release_shared(threadpool->srw_lock); - /* Codes_SRS_THREADPOOL_LINUX_05_042: [ If the is_pending_work_item_count_ptr_not_null is TRUE then: ]*/ - if (is_pending_work_item_count_ptr_not_null) - { - /* Codes_SRS_THREADPOOL_LINUX_05_043: [ threadpool_work_func shall acquire the exclusive SRW lock by calling srw_lock_acquire_exclusive. ]*/ - srw_lock_acquire_exclusive(threadpool->srw_lock); - /* Codes_SRS_THREADPOOL_LINUX_05_044: [ threadpool_work_func shall decrement the pending_work_item_count_ptr by calling interlocked_decrement. ]*/ - interlocked_decrement(threadpool->task_array[current_index].pending_work_item_count_ptr); - /* Codes_SRS_THREADPOOL_LINUX_05_045: [ threadpool_work_func shall send wake up signal to single listener for the address in pending_work_item_count_ptr. ]*/ - wake_by_address_single(threadpool->task_array[current_index].pending_work_item_count_ptr); - /* Codes_SRS_THREADPOOL_LINUX_05_046: [ threadpool_work_func shall release the shared SRW lock by calling srw_lock_release_exclusive. ]*/ - srw_lock_release_exclusive(threadpool->srw_lock); + + srw_lock_acquire_exclusive(threadpool->srw_lock); + if (NULL != threadpool->task_array[current_index].pending_work_item_count_ptr) + { + if (interlocked_decrement(threadpool->task_array[current_index].pending_work_item_count_ptr) == 0) + { + wake_by_address_single(threadpool->task_array[current_index].pending_work_item_count_ptr); + } } + srw_lock_release_exclusive(threadpool->srw_lock); } } } - /* Codes_SRS_THREADPOOL_LINUX_07_085: [ threadpool_work_func shall loop until threadpool_close or threadpool_destroy is called. ]*/ - } while (interlocked_add(&threadpool->run_thread, 0) != 1); + /* Codes_SRS_THREADPOOL_LINUX_07_085: [ threadpool_work_func shall loop until the flag to stop the threads is not set to 1. ]*/ + } while (interlocked_add(&threadpool->stop_thread, 0) != 1); } return 0; } @@ -277,7 +246,7 @@ static int reallocate_threadpool_array(THREADPOOL* threadpool) else { /* Codes_SRS_THREADPOOL_LINUX_07_043: [ threadpool_schedule_work shall initialize every task item in the new task array with task_func and task_param set to NULL and task_state set to TASK_NOT_USED. ]*/ - for (int32_t index = existing_count; index < new_task_array_size; index++) + for (uint32_t index = existing_count; index < new_task_array_size; index++) { temp_array[index].work_function = NULL; temp_array[index].work_function_ctx = NULL; @@ -325,18 +294,30 @@ static int reallocate_threadpool_array(THREADPOOL* threadpool) static void threadpool_dispose(THREADPOOL* threadpool) { - /* Codes_SRS_THREADPOOL_LINUX_07_013: [ threadpool_destroy shall perform an implicit close if threadpool is open. ]*/ - internal_close(threadpool); + /* Codes_SRS_THREADPOOL_LINUX_07_089: [ threadpool_dispose shall signal all threads to return. ]*/ + (void)InterlockedHL_SetAndWakeAll(&threadpool->stop_thread, 1); + for (uint32_t index = 0; index < threadpool->used_thread_count; index++) + { + int dont_care; + /* Codes_SRS_THREADPOOL_LINUX_07_027: [ threadpool_dispose shall join all threads in the threadpool. ]*/ + if (ThreadAPI_Join(threadpool->thread_handle_array[index], &dont_care) != THREADAPI_OK) + { + LogError("Failure joining thread number %" PRIu32 "", index); + } + else + { + // Everything Okay. + } + } - /* Codes_SRS_THREADPOOL_LINUX_07_016: [ threadpool_destroy shall free the memory allocated in threadpool_create. ]*/ + /* Codes_SRS_THREADPOOL_LINUX_07_016: [ threadpool_dispose shall free the memory allocated in threadpool_create. ]*/ free(threadpool->task_array); free(threadpool->thread_handle_array); - /* Codes_SRS_THREADPOOL_LINUX_07_014: [ threadpool_destroy shall destroy the semphore by calling sem_destroy. ]*/ + /* Codes_SRS_THREADPOOL_LINUX_07_014: [ threadpool_dispose shall destroy the semphore by calling sem_destroy. ]*/ sem_destroy(&threadpool->semaphore); - /* Codes_SRS_THREADPOOL_LINUX_07_015: [ threadpool_destroy shall destroy the SRW lock by calling srw_lock_destroy. ]*/ - srw_lock_destroy(threadpool->srw_lock); - sm_destroy(threadpool->sm); + /* Codes_SRS_THREADPOOL_LINUX_07_015: [ threadpool_dispose shall destroy the SRW lock by calling srw_lock_destroy. ]*/ + srw_lock_destroy(threadpool->srw_lock); } THANDLE(THREADPOOL) threadpool_create(EXECUTION_ENGINE_HANDLE execution_engine) @@ -359,84 +340,105 @@ THANDLE(THREADPOOL) threadpool_create(EXECUTION_ENGINE_HANDLE execution_engine) } else { - /* Codes_SRS_THREADPOOL_LINUX_07_003: [ threadpool_create shall create a SM_HANDLE by calling sm_create. ]*/ - result->sm = sm_create("threadpool"); - if(result->sm == NULL) + /* Codes_SRS_THREADPOOL_LINUX_07_004: [ threadpool_create shall get the min_thread_count and max_thread_count thread parameters from the execution_engine. ]*/ + const EXECUTION_ENGINE_PARAMETERS* param = execution_engine_linux_get_parameters(execution_engine); + + result->min_thread_count = param->min_thread_count; + result->max_thread_count = param->max_thread_count; + result->used_thread_count = result->min_thread_count; + + /* Codes_SRS_THREADPOOL_LINUX_07_005: [ threadpool_create shall allocate memory for an array of thread handles of size min_thread_count and on success return a non-NULL handle to it. ]*/ + result->thread_handle_array = malloc_2(result->used_thread_count, sizeof(THREAD_HANDLE)); + if (result->thread_handle_array == NULL) { /* Codes_SRS_THREADPOOL_LINUX_07_011: [ If any error occurs, threadpool_create shall fail and return NULL. ]*/ - LogError("sm_create failed."); + LogError("Failure malloc_2(result->used_thread_count: %" PRIu32 ", sizeof(THREAD_HANDLE)): %zu", result->used_thread_count, sizeof(THREAD_HANDLE)); } else { - /* Codes_SRS_THREADPOOL_LINUX_07_004: [ threadpool_create shall get the min_thread_count and max_thread_count thread parameters from the execution_engine. ]*/ - const EXECUTION_ENGINE_PARAMETERS* param = execution_engine_linux_get_parameters(execution_engine); - - result->min_thread_count = param->min_thread_count; - result->max_thread_count = param->max_thread_count; - result->used_thread_count = result->min_thread_count; - - /* Codes_SRS_THREADPOOL_LINUX_07_005: [ threadpool_create shall allocate memory for an array of thread handles of size min_thread_count and on success return a non-NULL handle to it. ]*/ - result->thread_handle_array = malloc_2(result->used_thread_count, sizeof(THREAD_HANDLE)); - if (result->thread_handle_array == NULL) + /* Codes_SRS_THREADPOOL_LINUX_07_006: [ threadpool_create shall allocate memory with default task array size 2048 for an array of tasks and on success return a non-NULL handle to it. ]*/ + result->task_array = malloc_2(DEFAULT_TASK_ARRAY_SIZE, sizeof(THREADPOOL_TASK)); + if (result->task_array == NULL) { /* Codes_SRS_THREADPOOL_LINUX_07_011: [ If any error occurs, threadpool_create shall fail and return NULL. ]*/ - LogError("Failure malloc_2(result->used_thread_count: %" PRIu32 ", sizeof(THREAD_HANDLE)): %zu", result->used_thread_count, sizeof(THREAD_HANDLE)); + LogError("Failure malloc_2(DEFAULT_TASK_ARRAY_SIZE: %" PRIu32 ", sizeof(THREADPOOL_TASK)): %zu", DEFAULT_TASK_ARRAY_SIZE, sizeof(THREADPOOL_TASK)); } else { - /* Codes_SRS_THREADPOOL_LINUX_07_006: [ threadpool_create shall allocate memory with default task array size 2048 for an array of tasks and on success return a non-NULL handle to it. ]*/ - result->task_array = malloc_2(DEFAULT_TASK_ARRAY_SIZE, sizeof(THREADPOOL_TASK)); - if (result->task_array == NULL) + result->task_array_size = DEFAULT_TASK_ARRAY_SIZE; + /* Codes_SRS_THREADPOOL_LINUX_07_007: [ threadpool_create shall initialize every task item in the tasks array with task_func and task_param set to NULL and task_state set to TASK_NOT_USED. ]*/ + for (uint32_t index = 0; index < result->task_array_size; index++) + { + result->task_array[index].work_function = NULL; + result->task_array[index].work_function_ctx = NULL; + result->task_array[index].pending_work_item_count_ptr = NULL; + (void)interlocked_exchange(&result->task_array[index].task_state, TASK_NOT_USED); + } + + /* Codes_SRS_THREADPOOL_LINUX_07_008: [ threadpool_create shall create a SRW lock by calling srw_lock_create. ]*/ + result->srw_lock = srw_lock_create(false, "threadpool_lock"); + if (result->srw_lock == NULL) { /* Codes_SRS_THREADPOOL_LINUX_07_011: [ If any error occurs, threadpool_create shall fail and return NULL. ]*/ - LogError("Failure malloc_2(DEFAULT_TASK_ARRAY_SIZE: %" PRIu32 ", sizeof(THREADPOOL_TASK)): %zu", DEFAULT_TASK_ARRAY_SIZE, sizeof(THREADPOOL_TASK)); + LogError("Failure srw_lock_create"); } else { - result->task_array_size = DEFAULT_TASK_ARRAY_SIZE; - /* Codes_SRS_THREADPOOL_LINUX_07_007: [ threadpool_create shall initialize every task item in the tasks array with task_func and task_param set to NULL and task_state set to TASK_NOT_USED. ]*/ - for (int32_t index = 0; index < result->task_array_size; index++) - { - result->task_array[index].work_function = NULL; - result->task_array[index].work_function_ctx = NULL; - result->task_array[index].pending_work_item_count_ptr = NULL; - (void)interlocked_exchange(&result->task_array[index].task_state, TASK_NOT_USED); - } - - /* Codes_SRS_THREADPOOL_LINUX_07_008: [ threadpool_create shall create a SRW lock by calling srw_lock_create. ]*/ - result->srw_lock = srw_lock_create(false, "threadpool_lock"); - if (result->srw_lock == NULL) + result->list_index = 0; + /* Codes_SRS_THREADPOOL_LINUX_07_009: [ threadpool_create shall create a shared semaphore with initialized value zero. ]*/ + if (sem_init(&result->semaphore, 0 , 0) != 0) { /* Codes_SRS_THREADPOOL_LINUX_07_011: [ If any error occurs, threadpool_create shall fail and return NULL. ]*/ - LogError("Failure srw_lock_create"); + LogError("Failure creating sem_init"); } else { - result->list_index = 0; - /* Codes_SRS_THREADPOOL_LINUX_07_009: [ threadpool_create shall create a shared semaphore with initialized value zero. ]*/ - if (sem_init(&result->semaphore, 0 , 0) != 0) + (void)interlocked_exchange(&result->stop_thread, 0); + (void)interlocked_exchange(&result->task_count, 0); + + /* Codes_SRS_THREADPOOL_LINUX_07_010: [ insert_idx and consume_idx for the task array shall be initialized to 0. ]*/ + (void)interlocked_exchange_64(&result->insert_idx, 0); + (void)interlocked_exchange_64(&result->consume_idx, 0); + + uint32_t index; + for (index = 0; index < result->used_thread_count; index++) + { + /* Codes_SRS_THREADPOOL_LINUX_07_020: [ threadpool_create shall create number of min_thread_count threads for threadpool using ThreadAPI_Create. ]*/ + if (ThreadAPI_Create(&result->thread_handle_array[index], threadpool_work_func, result) != THREADAPI_OK) + { + /* Codes_SRS_THREADPOOL_LINUX_07_011: [ If any error occurs, threadpool_create shall fail and return NULL. ]*/ + LogError("Failure creating thread %" PRIu32 "", index); + break; + } + } + + /* Codes_SRS_THREADPOOL_LINUX_07_022: [ If one of the thread creation fails, threadpool_create shall fail and return a non-zero value, terminate all threads already created. ]*/ + if (index < result->used_thread_count) { - /* Codes_SRS_THREADPOOL_LINUX_07_011: [ If any error occurs, threadpool_create shall fail and return NULL. ]*/ - LogError("Failure creating sem_init"); + (void)interlocked_exchange(&result->stop_thread, 1); + for (uint32_t inner = 0; inner < index; inner++) + { + int dont_care; + if (ThreadAPI_Join(result->thread_handle_array[inner], &dont_care) != THREADAPI_OK) + { + LogError("Failure joining thread number %" PRIu32 "", inner); + } + else + { + // Everything Okay. + } + } } else { - (void)interlocked_exchange(&result->run_thread, 0); - (void)interlocked_exchange(&result->task_count, 0); - - /* Codes_SRS_THREADPOOL_LINUX_07_010: [ insert_idx and consume_idx for the task array shall be initialized to 0. ]*/ - (void)interlocked_exchange_64(&result->insert_idx, 0); - (void)interlocked_exchange_64(&result->consume_idx, 0); - goto all_ok; } - srw_lock_destroy(result->srw_lock); } - free(result->task_array); + srw_lock_destroy(result->srw_lock); } - free(result->thread_handle_array); + free(result->task_array); } - sm_destroy(result->sm); + free(result->thread_handle_array); } THANDLE_FREE(THREADPOOL)(result); result = NULL; @@ -446,6 +448,7 @@ THANDLE(THREADPOOL) threadpool_create(EXECUTION_ENGINE_HANDLE execution_engine) return result; } +// threadpool_open will be deprecated and threadpool_create will perform additional tasks of threadpool_open. This function will exist until all the libraries calling this API are modified to use only threadpool_create. int threadpool_open(THANDLE(THREADPOOL) threadpool) { int result; @@ -459,68 +462,13 @@ int threadpool_open(THANDLE(THREADPOOL) threadpool) } else { - THREADPOOL* threadpool_ptr = THANDLE_GET_T(THREADPOOL)(threadpool); - - /* Codes_SRS_THREADPOOL_LINUX_07_018: [ threadpool_open shall call sm_open_begin. ]*/ - SM_RESULT open_result = sm_open_begin(threadpool_ptr->sm); - if(open_result != SM_EXEC_GRANTED) - { - /* Codes_SRS_THREADPOOL_LINUX_07_019: [ If sm_open_begin indicates the open cannot be performed, threadpool_open shall fail and return a non-zero value. ]*/ - LogError("sm_open_begin failed with %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, open_result)); - result = MU_FAILURE; - } - else - { - int32_t array_size = interlocked_add(&threadpool_ptr->task_array_size, 0); - // Codes_SRS_THREADPOOL_LINUX_11_001: [ threadpool_open shall initialize internal threapool data items ] - for (int32_t index = 0; index < array_size; index++) - { - threadpool_ptr->task_array[index].work_function = NULL; - threadpool_ptr->task_array[index].work_function_ctx = NULL; - (void)interlocked_exchange(&threadpool_ptr->task_array[index].task_state, TASK_NOT_USED); - } - (void)interlocked_exchange(&threadpool_ptr->run_thread, 0); - (void)interlocked_exchange_64(&threadpool_ptr->insert_idx, 0); - (void)interlocked_exchange_64(&threadpool_ptr->consume_idx, 0); - - int32_t index; - for (index = 0; index < threadpool_ptr->used_thread_count; index++) - { - /* Codes_SRS_THREADPOOL_LINUX_07_020: [ threadpool_open shall create number of min_thread_count threads for threadpool using ThreadAPI_Create. ]*/ - if (ThreadAPI_Create(&threadpool_ptr->thread_handle_array[index], threadpool_work_func, threadpool_ptr) != THREADAPI_OK) - { - /* Codes_SRS_THREADPOOL_LINUX_07_021: [ If any error occurs, threadpool_open shall fail and return a non-zero value. ]*/ - LogError("Failure creating thread %" PRId32 "", index); - break; - } - } - - /* Codes_SRS_THREADPOOL_LINUX_07_022: [ If one of the thread creation fails, threadpool_open shall fail and return a non-zero value, terminate all threads already created. ]*/ - if (index < threadpool_ptr->used_thread_count) - { - for (int32_t inner = 0; inner < index; inner++) - { - int dont_care; - if (ThreadAPI_Join(threadpool_ptr->thread_handle_array[inner], &dont_care) != THREADAPI_OK) - { - LogError("Failure joining thread number %" PRId32 "", inner); - } - } - sm_open_end(threadpool_ptr->sm, false); - result = MU_FAILURE; - } - else - { - /* Codes_SRS_THREADPOOL_LINUX_07_023: [ Otherwise, threadpool_open shall shall call sm_open_end with true for success. ]*/ - sm_open_end(threadpool_ptr->sm, true); - /* Codes_SRS_THREADPOOL_LINUX_07_024: [ threadpool_open shall succeed and return zero. ]*/ - result = 0; - } - } + /* Codes_SRS_THREADPOOL_LINUX_07_024: [ Otherwise, threadpool_open shall succeed and return 0. ]*/ + result = 0; } return result; } +// threadpool_close will be deprecated and threadpool_dispose will perform additional tasks of threadpool_close. This function will exist until all the libraries calling this API are modified to use only threadpool_create. void threadpool_close(THANDLE(THREADPOOL) threadpool) { /* Codes_SRS_THREADPOOL_LINUX_07_025: [ If threadpool is NULL, threadpool_close shall fail and return. ]*/ @@ -528,11 +476,6 @@ void threadpool_close(THANDLE(THREADPOOL) threadpool) { LogError("THANDLE(THREADPOOL) threadpool=%p", threadpool); } - else - { - THREADPOOL* threadpool_ptr = THANDLE_GET_T(THREADPOOL)(threadpool); - internal_close(threadpool_ptr); - } } int threadpool_schedule_work(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUNCTION work_function, void* work_function_ctx) @@ -551,65 +494,52 @@ int threadpool_schedule_work(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUN { THREADPOOL* threadpool_ptr = THANDLE_GET_T(THREADPOOL)(threadpool); - /* Codes_SRS_THREADPOOL_LINUX_07_031: [ threadpool_schedule_work shall call sm_exec_begin. ]*/ - SM_RESULT sm_result = sm_exec_begin(threadpool_ptr->sm); - if (sm_result != SM_EXEC_GRANTED) - { - /* Codes_SRS_THREADPOOL_LINUX_07_032: [ If sm_exec_begin returns SM_EXEC_REFUSED, threadpool_schedule_work shall fail and return a non-zero value. ]*/ - LogError("sm_exec_begin failed : %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, sm_result)); - result = MU_FAILURE; - } - else + + do { - do - { - /* Codes_SRS_THREADPOOL_LINUX_07_033: [ threadpool_schedule_work shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ - srw_lock_acquire_shared(threadpool_ptr->srw_lock); - int32_t existing_count = interlocked_add(&threadpool_ptr->task_array_size, 0); + /* Codes_SRS_THREADPOOL_LINUX_07_033: [ threadpool_schedule_work shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ + srw_lock_acquire_shared(threadpool_ptr->srw_lock); + int32_t existing_count = interlocked_add(&threadpool_ptr->task_array_size, 0); - /* Codes_SRS_THREADPOOL_LINUX_07_034: [ threadpool_schedule_work shall increment the insert_pos. ]*/ - int64_t insert_pos = (interlocked_increment_64(&threadpool_ptr->insert_idx) - 1) % existing_count; + /* Codes_SRS_THREADPOOL_LINUX_07_034: [ threadpool_schedule_work shall increment the insert_pos. ]*/ + int64_t insert_pos = (interlocked_increment_64(&threadpool_ptr->insert_idx) - 1) % existing_count; - /* Codes_SRS_THREADPOOL_LINUX_07_035: [ If task state is TASK_NOT_USED, threadpool_schedule_work shall set the current task state to TASK_INITIALIZING. ]*/ - int32_t task_state = interlocked_compare_exchange(&threadpool_ptr->task_array[insert_pos].task_state, TASK_INITIALIZING, TASK_NOT_USED); + /* Codes_SRS_THREADPOOL_LINUX_07_035: [ If task state is TASK_NOT_USED, threadpool_schedule_work shall set the current task state to TASK_INITIALIZING. ]*/ + int32_t task_state = interlocked_compare_exchange(&threadpool_ptr->task_array[insert_pos].task_state, TASK_INITIALIZING, TASK_NOT_USED); - if (task_state != TASK_NOT_USED) - { - /* Codes_SRS_THREADPOOL_LINUX_07_036: [ Otherwise, threadpool_schedule_work shall release the shared SRW lock by calling srw_lock_release_shared and increase task_array capacity: ]*/ - srw_lock_release_shared(threadpool_ptr->srw_lock); + if (task_state != TASK_NOT_USED) + { + /* Codes_SRS_THREADPOOL_LINUX_07_036: [ Otherwise, threadpool_schedule_work shall release the shared SRW lock by calling srw_lock_release_shared and increase task_array capacity: ]*/ + srw_lock_release_shared(threadpool_ptr->srw_lock); - if (reallocate_threadpool_array(threadpool_ptr) != 0) - { - /* Codes_SRS_THREADPOOL_LINUX_07_048: [ If reallocating the task array fails, threadpool_schedule_work shall fail and return a non-zero value. ]*/ - LogError("Failure reallocating threadpool_ptr"); - result = MU_FAILURE; - break; - } - continue; - } - /* Codes_SRS_THREADPOOL_LINUX_07_049: [ threadpool_schedule_work shall initialize pending_work_item_count_ptr with NULL then copy the work function and work function context into insert position in the task array and assign 0 to the return variable to indicate success. ] */ - else + if (reallocate_threadpool_array(threadpool_ptr) != 0) { - THREADPOOL_TASK* task_item = &threadpool_ptr->task_array[insert_pos]; - task_item->work_function_ctx = work_function_ctx; - task_item->work_function = work_function; - task_item->pending_work_item_count_ptr = NULL; + /* Codes_SRS_THREADPOOL_LINUX_07_048: [ If reallocating the task array fails, threadpool_schedule_work shall fail and return a non-zero value. ]*/ + LogError("Failure reallocating threadpool_ptr"); + result = MU_FAILURE; + break; + } + continue; + } + /* Codes_SRS_THREADPOOL_LINUX_07_049: [ threadpool_schedule_work shall copy the work function and work function context into insert position in the task array and assign 0 to the return variable to indicate success. ] */ + else + { + THREADPOOL_TASK* task_item = &threadpool_ptr->task_array[insert_pos]; + task_item->work_function_ctx = work_function_ctx; + task_item->work_function = work_function; - /* Codes_SRS_THREADPOOL_LINUX_07_050: [ threadpool_schedule_work shall set the task_state to TASK_WAITING and then release the shared SRW lock. ] */ - (void)interlocked_exchange(&task_item->task_state, TASK_WAITING); - srw_lock_release_shared(threadpool_ptr->srw_lock); + /* Codes_SRS_THREADPOOL_LINUX_07_050: [ threadpool_schedule_work shall set the task_state to TASK_WAITING and then release the shared SRW lock. ] */ + (void)interlocked_exchange(&task_item->task_state, TASK_WAITING); + srw_lock_release_shared(threadpool_ptr->srw_lock); - /* Codes_SRS_THREADPOOL_LINUX_07_051: [ threadpool_schedule_work shall unblock the threadpool semaphore by calling sem_post. ]*/ - sem_post(&threadpool_ptr->semaphore); + /* Codes_SRS_THREADPOOL_LINUX_07_051: [ threadpool_schedule_work shall unblock the threadpool semaphore by calling sem_post. ]*/ + sem_post(&threadpool_ptr->semaphore); - /* Codes_SRS_THREADPOOL_LINUX_07_047: [ threadpool_schedule_work shall return zero on success. ]*/ - result = 0; - break; - } - } while (true); - /* Codes_SRS_THREADPOOL_LINUX_07_053: [ threadpool_schedule_work shall call sm_exec_end. ]*/ - sm_exec_end(threadpool_ptr->sm); - } + /* Codes_SRS_THREADPOOL_LINUX_07_047: [ threadpool_schedule_work shall return zero on success. ]*/ + result = 0; + break; + } + } while (true); } return result; } @@ -807,9 +737,9 @@ THREADPOOL_WORK_ITEM_HANDLE threadpool_create_work_item(THANDLE(THREADPOOL) thre THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item = NULL; if ( - /* Codes_SRS_THREADPOOL_LINUX_05_001: [ If threadpool is NULL, threadpool_create_work_item shall fail and set the return variable threadpool_work_item a NULL value. ] */ + /* Codes_SRS_THREADPOOL_LINUX_05_001: [ If threadpool is NULL, threadpool_create_work_item shall fail and return a NULL value. ] */ (threadpool == NULL) || - /* Codes_SRS_THREADPOOL_LINUX_05_002: [ If work_function is NULL, threadpool_create_work_item shall fail and set the return variable threadpool_work_item a NULL value. ]*/ + /* Codes_SRS_THREADPOOL_LINUX_05_002: [ If work_function is NULL, threadpool_create_work_item shall fail and return a NULL value. ]*/ (work_function == NULL) ) { @@ -817,37 +747,22 @@ THREADPOOL_WORK_ITEM_HANDLE threadpool_create_work_item(THANDLE(THREADPOOL) thre } else { - THREADPOOL* threadpool_ptr = THANDLE_GET_T(THREADPOOL)(threadpool); + /* Codes_SRS_THREADPOOL_LINUX_05_005: [ threadpool_create_work_item shall allocate memory for threadpool_work_item of type THREADPOOL_WORK_ITEM_HANDLE. ] */ + threadpool_work_item = (THREADPOOL_WORK_ITEM_HANDLE)malloc(sizeof(THREADPOOL_WORK_ITEM)); - /* Codes_SRS_THREADPOOL_LINUX_05_003: [ threadpool_create_work_item` shall call sm_exec_begin. ] */ - SM_RESULT open_result = sm_exec_begin(threadpool_ptr->sm); - if (open_result != SM_EXEC_GRANTED) + if (threadpool_work_item == NULL) { - /* Codes_SRS_THREADPOOL_LINUX_05_004: [ If sm_exec_begin returns SM_EXEC_REFUSED, threadpool_create_work_item shall fail and set the return variable threadpool_work_item a NULL value. ]*/ - LogError("sm_exec_begin failed with %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, open_result)); + /* Codes_SRS_THREADPOOL_LINUX_05_006: [ If during the initialization of threadpool_work_item, malloc fails then threadpool_create_work_item shall fail and return a NULL value. ]*/ + LogError("Could not allocate memory for Work Item Context"); } else { - /* Codes_SRS_THREADPOOL_LINUX_05_005: [ threadpool_create_work_item shall allocate memory for threadpool_work_item of type THREADPOOL_WORK_ITEM_HANDLE. ] */ - threadpool_work_item = (THREADPOOL_WORK_ITEM_HANDLE)malloc(sizeof(THREADPOOL_WORK_ITEM)); - - if (threadpool_work_item == NULL) - { - /* Codes_SRS_THREADPOOL_LINUX_05_006: [ If during the initialization of threadpool_work_item, malloc fails then threadpool_create_work_item shall fail. ]*/ - LogError("Could not allocate memory for Work Item Context"); - } - else - { - /* Codes_SRS_THREADPOOL_LINUX_05_007: [ threadpool_create_work_item shall initialize pending_work_item_count to 0 then copy the work_function and work_function_context into the threadpool_work_item and an initialized threadpool_work_item when returned indicates success. ] */ - interlocked_exchange(&threadpool_work_item->pending_work_item_count, 0); - threadpool_work_item->work_function_ctx = work_function_context; - threadpool_work_item->work_function = work_function; - } - /* Codes_SRS_THREADPOOL_LINUX_05_008: [ threadpool_create_work_item shall call sm_exec_end. ]*/ - sm_exec_end(threadpool_ptr->sm); - } + /* Codes_SRS_THREADPOOL_LINUX_05_007: [ threadpool_create_work_item shall copy the work_function and work_function_context into the threadpool work item. ] */ + (void)interlocked_exchange(&threadpool_work_item->pending_work_item_count, 0); + threadpool_work_item->work_function_ctx = work_function_context; + threadpool_work_item->work_function = work_function; + } } - /* Codes_SRS_THREADPOOL_LINUX_05_009: [ Return the value inside threadpool_work_item ]*/ return threadpool_work_item; } @@ -855,9 +770,9 @@ int threadpool_schedule_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WOR { int result; if ( - /* Codes_SRS_THREADPOOL_LINUX_05_010: [ If threadpool is NULL, threadpool_schedule_work_item shall fail and set the return variable with a non-zero value. ]*/ + /* Codes_SRS_THREADPOOL_LINUX_05_010: [ If threadpool is NULL, threadpool_schedule_work_item shall fail and return a non-zero value. ]*/ (threadpool == NULL) || - /* Codes_SRS_THREADPOOL_LINUX_05_011: [ If threadpool_work_item is NULL, threadpool_schedule_work_item shall fail and set the return variable with a non-zero value. ] */ + /* Codes_SRS_THREADPOOL_LINUX_05_011: [ If threadpool_work_item is NULL, threadpool_schedule_work_item shall fail and return a non-zero value. ] */ (threadpool_work_item == NULL) ) { @@ -868,76 +783,62 @@ int threadpool_schedule_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WOR { THREADPOOL* threadpool_ptr = THANDLE_GET_T(THREADPOOL)(threadpool); - /* Codes_SRS_THREADPOOL_LINUX_05_012: [ threadpool_schedule_work_item shall call sm_exec_begin. ]*/ - SM_RESULT sm_result = sm_exec_begin(threadpool_ptr->sm); - if (sm_result != SM_EXEC_GRANTED) - { - /* Codes_SRS_THREADPOOL_LINUX_05_013: [ If sm_exec_begin returns SM_EXEC_REFUSED, threadpool_schedule_work_item shall fail and set the return variable a non-zero value. ]*/ - LogError("sm_exec_begin failed : %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, sm_result)); - result = MU_FAILURE; - } - else + do { - do - { - /* Codes_SRS_THREADPOOL_LINUX_05_014: [ threadpool_schedule_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ - srw_lock_acquire_shared(threadpool_ptr->srw_lock); - int32_t existing_count = interlocked_add(&threadpool_ptr->task_array_size, 0); + /* Codes_SRS_THREADPOOL_LINUX_05_014: [ threadpool_schedule_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ + srw_lock_acquire_shared(threadpool_ptr->srw_lock); + int32_t existing_count = interlocked_add(&threadpool_ptr->task_array_size, 0); - /* Codes_SRS_THREADPOOL_LINUX_05_015: [ threadpool_schedule_work_item shall increment the insert_pos. ]*/ - int64_t insert_pos = (interlocked_increment_64(&threadpool_ptr->insert_idx) - 1) % existing_count; + /* Codes_SRS_THREADPOOL_LINUX_05_015: [ threadpool_schedule_work_item shall increment the insert_pos. ]*/ + int64_t insert_pos = (interlocked_increment_64(&threadpool_ptr->insert_idx) - 1) % existing_count; - /* Codes_SRS_THREADPOOL_LINUX_05_016: [ If task state is TASK_NOT_USED, threadpool_schedule_work_item shall set the current task state to TASK_INITIALIZING. ]*/ - int32_t task_state = interlocked_compare_exchange(&threadpool_ptr->task_array[insert_pos].task_state, TASK_INITIALIZING, TASK_NOT_USED); + /* Codes_SRS_THREADPOOL_LINUX_05_016: [ If task state is TASK_NOT_USED, threadpool_schedule_work_item shall set the current task state to TASK_INITIALIZING. ]*/ + int32_t task_state = interlocked_compare_exchange(&threadpool_ptr->task_array[insert_pos].task_state, TASK_INITIALIZING, TASK_NOT_USED); - /* Codes_SRS_THREADPOOL_LINUX_05_017: [ threadpool_schedule_work_item shall release the shared SRW lock by calling srw_lock_release_shared. ]*/ - srw_lock_release_shared(threadpool_ptr->srw_lock); - /* Codes_SRS_THREADPOOL_LINUX_05_018: [ If the previous task state is not TASK_NOT_USED then threadpool_schedule_work_item shall increase task_array capacity. ]*/ - if (task_state != TASK_NOT_USED) + /* Codes_SRS_THREADPOOL_LINUX_05_017: [ threadpool_schedule_work_item shall release the shared SRW lock by calling srw_lock_release_shared. ]*/ + srw_lock_release_shared(threadpool_ptr->srw_lock); + /* Codes_SRS_THREADPOOL_LINUX_05_018: [ If the previous task state is not TASK_NOT_USED then threadpool_schedule_work_item shall increase task_array capacity. ]*/ + if (task_state != TASK_NOT_USED) + { + if (reallocate_threadpool_array(threadpool_ptr) != 0) { - if (reallocate_threadpool_array(threadpool_ptr) != 0) - { - /* Codes_SRS_THREADPOOL_LINUX_05_019: [ If reallocating the task array fails, threadpool_schedule_work_item shall fail by setting the return variable a non-zero value and break. ]*/ - LogError("Failure reallocating threadpool_ptr"); - result = MU_FAILURE; - break; - } - continue; + /* Codes_SRS_THREADPOOL_LINUX_05_019: [ If reallocating the task array fails, threadpool_schedule_work_item shall fail and return a non-zero value. ]*/ + LogError("Failure reallocating threadpool_ptr"); + result = MU_FAILURE; + break; } - else - { - /* Codes_SRS_THREADPOOL_LINUX_05_020: [ threadpool_schedule_work_item shall acquire the SRW lock in exclusive mode by calling srw_lock_acquire_exclusive. ]*/ - srw_lock_acquire_exclusive(threadpool_ptr->srw_lock); - THREADPOOL_TASK* task_item = &threadpool_ptr->task_array[insert_pos]; - /* Codes_SRS_THREADPOOL_LINUX_05_021: [ threadpool_schedule_work_item shall increment the pending_work_item_count and copy its address to pending_work_item_count_ptr into insert position in the task array. ]*/ - interlocked_increment(&threadpool_work_item->pending_work_item_count); - task_item->pending_work_item_count_ptr = &threadpool_work_item->pending_work_item_count; + continue; + } + else + { + /* Codes_SRS_THREADPOOL_LINUX_05_020: [ threadpool_schedule_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_exclusive. ]*/ + srw_lock_acquire_shared(threadpool_ptr->srw_lock); + THREADPOOL_TASK* task_item = &threadpool_ptr->task_array[insert_pos]; + + (void)interlocked_increment(&threadpool_work_item->pending_work_item_count); - /* Codes_SRS_THREADPOOL_LINUX_05_022: [ threadpool_schedule_work_item shall copy the work_function and work_function_context from threadpool_work_item into insert position in the task array. ]*/ - task_item->work_function_ctx = threadpool_work_item->work_function_ctx; - task_item->work_function = threadpool_work_item->work_function; + /* Codes_SRS_THREADPOOL_LINUX_05_022: [ threadpool_schedule_work_item shall copy the work_function and work_function_context from threadpool_work_item into insert position in the task array. ]*/ + task_item->work_function_ctx = threadpool_work_item->work_function_ctx; + task_item->work_function = threadpool_work_item->work_function; - /* Codes_SRS_THREADPOOL_LINUX_05_023: [ threadpool_schedule_work_item shall set the task_state to TASK_WAITING and then release the exclusive SRW lock by calling srw_lock_release_exclusive. ]*/ - interlocked_exchange(&task_item->task_state, TASK_WAITING); + /* Codes_SRS_THREADPOOL_LINUX_05_023: [ threadpool_schedule_work_item shall set the task_state to TASK_WAITING and then release the shared SRW lock by calling srw_lock_release_exclusive. ]*/ + (void)interlocked_exchange(&task_item->task_state, TASK_WAITING); - /* Codes_SRS_THREADPOOL_LINUX_05_024: [ threadpool_schedule_work_item shall notify a single thread that is waiting for update of this value by a wake signal. ]*/ - wake_by_address_single(task_item->pending_work_item_count_ptr); + srw_lock_release_shared(threadpool_ptr->srw_lock); - srw_lock_release_exclusive(threadpool_ptr->srw_lock); + srw_lock_acquire_exclusive(threadpool_ptr->srw_lock); + task_item->pending_work_item_count_ptr = &threadpool_work_item->pending_work_item_count; + srw_lock_release_exclusive(threadpool_ptr->srw_lock); - /* Codes_SRS_THREADPOOL_LINUX_05_025: [ threadpool_schedule_work_item shall unblock the threadpool semaphore by calling sem_post. ]*/ - sem_post(&threadpool_ptr->semaphore); + /* Codes_SRS_THREADPOOL_LINUX_05_025: [ threadpool_schedule_work_item shall unblock the threadpool semaphore by calling sem_post. ]*/ + sem_post(&threadpool_ptr->semaphore); - /* Codes_SRS_THREADPOOL_LINUX_05_026: [ threadpool_schedule_work_item shall set the return variable to 0 to indicate success. ]*/ - result = 0; - break; - } - } while (true); - /* Codes_SRS_THREADPOOL_LINUX_05_027: [ threadpool_schedule_work_item shall call sm_exec_end. ]*/ - sm_exec_end(threadpool_ptr->sm); - } + /* Codes_SRS_THREADPOOL_LINUX_05_026: [ threadpool_schedule_work_item shall succeed and return 0. ]*/ + result = 0; + break; + } + } while (true); } - /* Codes_SRS_THREADPOOL_LINUX_05_028: [ threadpool_schedule_work_item shall return with the contents of the value of the return variable. ]*/ return result; } @@ -953,35 +854,17 @@ void threadpool_destroy_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WOR LogError("Invalid arguments: THANDLE(THREADPOOL) threadpool: %p, THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item: %p", threadpool, threadpool_work_item); } else - { - THREADPOOL* threadpool_ptr = THANDLE_GET_T(THREADPOOL)(threadpool); - - /* Codes_SRS_THREADPOOL_LINUX_05_031: [ threadpool_destroy_work_item shall call sm_exec_begin ]*/ - SM_RESULT sm_result = sm_exec_begin(threadpool_ptr->sm); - if (sm_result != SM_EXEC_GRANTED) + { + /* Codes_SRS_THREADPOOL_LINUX_05_033: [ threadpool_destroy_work_item shall wait for all pending work items to finish execution. ]*/ + if (InterlockedHL_WaitForValue(&threadpool_work_item->pending_work_item_count, 0, UINT32_MAX) == INTERLOCKED_HL_OK) { - /* Codes_SRS_THREADPOOL_LINUX_05_032: [ If sm_exec_begin returns SM_EXEC_REFUSED, threadpool_destroy_work_item shall fail. ]*/ - LogError("sm_exec_begin failed : %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, sm_result)); + /* Codes_SRS_THREADPOOL_LINUX_05_035: [ threadpool_destroy_work_item shall free the memory allocated to the work item of type THREADPOOL_WORK_ITEM_HANDLE created in threadpool_create_work_item. ]*/ + free(threadpool_work_item); } else { - /* Codes_SRS_THREADPOOL_LINUX_05_033: [ Otherwise, threadpool_destroy_work_item shall wait for pending_work_item_count to become 0. ]*/ - if (InterlockedHL_WaitForValue(&threadpool_work_item->pending_work_item_count, 0, UINT32_MAX) == INTERLOCKED_HL_OK) - { - /* Codes_SRS_THREADPOOL_LINUX_05_034: [ When pending_work_item_count becomes 0, threadpool_destroy_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ - srw_lock_acquire_shared(threadpool_ptr->srw_lock); - /* Codes_SRS_THREADPOOL_LINUX_05_035: [ threadpool_destroy_work_item shall free the memory allocated to the work item of type THREADPOOL_WORK_ITEM_HANDLE created in threadpool_create_work_item. ]*/ - free(threadpool_work_item); - /* Codes_SRS_THREADPOOL_LINUX_05_036: [ threadpool_destroy_work_item shall release the shared SRW lock. ]*/ - srw_lock_release_shared(threadpool_ptr->srw_lock); - } - else - { - /* Codes_SRS_THREADPOOL_LINUX_05_037: [ If InterlockedHL_WaitForValue returns error then log the error and terminate. ]*/ - LogCriticalAndTerminate("Failure in InterlockedHL_WaitForValue(&threadpool_work_item->pending_work_item_count=%p, 0, UINT32_MAX), count was %d", &threadpool_work_item->pending_work_item_count, threadpool_work_item->pending_work_item_count); - } + /* Codes_SRS_THREADPOOL_LINUX_05_037: [ If InterlockedHL_WaitForValue returns error then log the error and terminate. ]*/ + LogCriticalAndTerminate("Failure in InterlockedHL_WaitForValue(&threadpool_work_item->pending_work_item_count=%p, 0, UINT32_MAX), count was %d", &threadpool_work_item->pending_work_item_count, threadpool_work_item->pending_work_item_count); } - /* Codes_SRS_THREADPOOL_LINUX_05_038: [ threadpool_destroy_work_item shall call sm_exec_end. ]*/ - sm_exec_end(threadpool_ptr->sm); } } \ No newline at end of file diff --git a/linux/tests/threadpool_linux_int/threadpool_linux_int.c b/linux/tests/threadpool_linux_int/threadpool_linux_int.c index 8a9b1af2..fdf11fab 100644 --- a/linux/tests/threadpool_linux_int/threadpool_linux_int.c +++ b/linux/tests/threadpool_linux_int/threadpool_linux_int.c @@ -20,6 +20,7 @@ #include "c_pal/threadpool.h" #include "c_pal/threadapi.h" #include "c_pal/interlocked.h" +#include "c_pal/srw_lock.h" #include "c_pal/sync.h" #include "c_pal/interlocked_hl.h" #include "c_pal/execution_engine.h" @@ -41,6 +42,7 @@ typedef struct WRAP_DATA_TAG } WRAP_DATA; #define TEST_TIMEOUT_VALUE 60000 // 60 seconds +#define XTEST_FUNCTION(A) void A(void) TEST_DEFINE_ENUM_TYPE(INTERLOCKED_HL_RESULT, INTERLOCKED_HL_RESULT_VALUES); @@ -97,13 +99,15 @@ static void threadpool_task_wait_random(void* parameter) wake_by_address_single(thread_counter); } +#define WRAP_TEST_WORK_ITEMS 10000 static void threadpool_long_task(void* context) { WRAP_DATA* data = context; ASSERT_ARE_EQUAL(int, 0, strcmp(data->mem, "READY")); strcpy(data->mem, "DONE"); - (void)interlocked_increment(data->counter); + ThreadAPI_Sleep(1); + interlocked_increment(data->counter); wake_by_address_single(data->counter); free(data); } @@ -111,9 +115,9 @@ static void threadpool_long_task(void* context) static void threadpool_long_task_v2(void* context) { WRAP_DATA* data = context; - ASSERT_ARE_EQUAL(int, 0, strcmp(data->mem, "READY")); + ASSERT_ARE_EQUAL(int, 0, strcmp(data->mem, "READY")); ThreadAPI_Sleep(1); - (void)interlocked_increment(data->counter); + interlocked_increment(data->counter); wake_by_address_single(data->counter); } @@ -165,9 +169,7 @@ TEST_FUNCTION(one_work_item_schedule_works) volatile_atomic int32_t thread_counter = 0; THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); - ASSERT_IS_NOT_NULL(threadpool); - - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); + ASSERT_IS_NOT_NULL(threadpool); // Create 1 thread pool LogInfo("Scheduling work item"); @@ -178,8 +180,7 @@ TEST_FUNCTION(one_work_item_schedule_works) ASSERT_ARE_EQUAL(int, INTERLOCKED_HL_OK, InterlockedHL_WaitForValue(&thread_counter, num_threads, UINT32_MAX)); ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); - // cleanup - threadpool_close(threadpool); + // cleanup THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } @@ -198,8 +199,6 @@ TEST_FUNCTION(one_work_item_schedule_work_item) THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - LogInfo("Creating work item"); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item = threadpool_create_work_item(threadpool, threadpool_task_wait_20_millisec, (void*)&thread_counter); ASSERT_IS_NOT_NULL(threadpool_work_item); @@ -213,8 +212,7 @@ TEST_FUNCTION(one_work_item_schedule_work_item) ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); // cleanup - threadpool_destroy_work_item(threadpool, threadpool_work_item); - threadpool_close(threadpool); + threadpool_destroy_work_item(threadpool, threadpool_work_item); THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } @@ -232,9 +230,7 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _work_items)) volatile_atomic int32_t thread_counter = 0; THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); - ASSERT_IS_NOT_NULL(threadpool); - - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); + ASSERT_IS_NOT_NULL(threadpool); // Create Work Items LogInfo("Creating work item once"); @@ -255,8 +251,7 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _work_items)) ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); // cleanup - threadpool_destroy_work_item(threadpool, threadpool_work_item); - threadpool_close(threadpool); + threadpool_destroy_work_item(threadpool, threadpool_work_item); THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } @@ -274,8 +269,6 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _work)) THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - // Create double the amount of threads that is the max LogInfo("Scheduling %" PRIu32 " work item", num_threads); for (uint32_t index = 0; index < num_threads; index++) @@ -289,8 +282,7 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _work)) ASSERT_ARE_EQUAL(int, INTERLOCKED_HL_OK, InterlockedHL_WaitForValue(&thread_counter, num_threads, UINT32_MAX)); ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); - // cleanup - threadpool_close(threadpool); + // cleanup THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } @@ -309,8 +301,6 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _work_items_with_pool_threads)) THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - // Create Work Items LogInfo("Creating work item once"); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item = threadpool_create_work_item(threadpool, threadpool_task_wait_20_millisec, (void*)&thread_counter); @@ -328,8 +318,7 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _work_items_with_pool_threads)) ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); // cleanup - threadpool_destroy_work_item(threadpool, threadpool_work_item); - threadpool_close(threadpool); + threadpool_destroy_work_item(threadpool, threadpool_work_item); THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } @@ -348,8 +337,6 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _work_with_pool_threads)) THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - // Create double the amount of threads that is the max LogInfo("Scheduling %" PRIu32 " work item with 20 millisecons work", num_threads); for (uint32_t index = 0; index < num_threads; index++) @@ -361,8 +348,7 @@ TEST_FUNCTION(MU_C3(scheduling_, N_WORK_ITEMS, _work_with_pool_threads)) ASSERT_ARE_EQUAL(int, INTERLOCKED_HL_OK, InterlockedHL_WaitForValue(&thread_counter, num_threads, UINT32_MAX)); ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); - // cleanup - threadpool_close(threadpool); + // cleanup THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } @@ -383,8 +369,6 @@ TEST_FUNCTION(threadpool_chaos_knight) THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - // Create double the amount of threads that is the max LogInfo("Scheduling %" PRIu32 " work items", num_threads); for (uint32_t index = 0; index < num_threads; index++) @@ -399,8 +383,7 @@ TEST_FUNCTION(threadpool_chaos_knight) ASSERT_ARE_EQUAL(int, INTERLOCKED_HL_OK, InterlockedHL_WaitForValue(&thread_counter, num_threads, UINT32_MAX)); ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); - // cleanup - threadpool_close(threadpool); + // cleanup THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } @@ -419,8 +402,6 @@ TEST_FUNCTION(threadpool_chaos_knight_v2) THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - // Create Work Items LogInfo("Creating work item once"); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item = threadpool_create_work_item(threadpool, threadpool_task_wait_random, (void*)&thread_counter); @@ -441,14 +422,11 @@ TEST_FUNCTION(threadpool_chaos_knight_v2) ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); // cleanup - threadpool_destroy_work_item(threadpool, threadpool_work_item); - threadpool_close(threadpool); + threadpool_destroy_work_item(threadpool, threadpool_work_item); THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } -#define WRAP_TEST_WORK_ITEMS 10000 - TEST_FUNCTION(threadpool_force_wrap_around) { // arrange @@ -456,14 +434,13 @@ TEST_FUNCTION(threadpool_force_wrap_around) EXECUTION_ENGINE_PARAMETERS params; params.min_thread_count = 1; - params.max_thread_count = num_threads; + params.max_thread_count = 16; EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(¶ms); THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - + volatile_atomic int32_t thread_counter; interlocked_exchange(&thread_counter, 0); @@ -480,8 +457,7 @@ TEST_FUNCTION(threadpool_force_wrap_around) ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); // cleanup - threadpool_close(threadpool); - THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); + THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } @@ -491,19 +467,19 @@ TEST_FUNCTION(threadpool_force_wrap_around_v2) const uint32_t num_threads = WRAP_TEST_WORK_ITEMS; EXECUTION_ENGINE_PARAMETERS params; params.min_thread_count = 1; - params.max_thread_count = num_threads; + params.max_thread_count = 16; EXECUTION_ENGINE_HANDLE execution_engine = execution_engine_create(¶ms); THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - + volatile_atomic int32_t thread_counter; interlocked_exchange(&thread_counter, 0); WRAP_DATA* data = malloc(sizeof(WRAP_DATA)); - data->counter = &thread_counter; + data->counter = &thread_counter; + strcpy(data->mem, "READY"); // Create Work Items THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item = threadpool_create_work_item(threadpool, threadpool_long_task_v2, data); @@ -520,9 +496,8 @@ TEST_FUNCTION(threadpool_force_wrap_around_v2) // cleanup - threadpool_destroy_work_item(threadpool, threadpool_work_item); + threadpool_destroy_work_item(threadpool, threadpool_work_item); free(data); - threadpool_close(threadpool); THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } @@ -807,7 +782,7 @@ TEST_FUNCTION(cancel_timer_waits_for_ongoing_execution) execution_engine_dec_ref(execution_engine); } -TEST_FUNCTION(schedule_after_close_works) +TEST_FUNCTION(schedule_work_two_times) { // assert EXECUTION_ENGINE_PARAMETERS params; @@ -821,8 +796,6 @@ TEST_FUNCTION(schedule_after_close_works) THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item = threadpool_create_work_item(threadpool, threadpool_task_wait_20_millisec, (void*)&thread_counter); ASSERT_IS_NOT_NULL(threadpool_work_item); @@ -832,20 +805,13 @@ TEST_FUNCTION(schedule_after_close_works) // assert LogInfo("Waiting for task to complete"); - do - { - (void)InterlockedHL_WaitForValue(&thread_counter, num_threads, TEST_TIMEOUT_VALUE); - } while (interlocked_add(&thread_counter, 0) != num_threads); + ASSERT_ARE_EQUAL(int, INTERLOCKED_HL_OK, InterlockedHL_WaitForValue(&thread_counter, num_threads, UINT32_MAX)); ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); - threadpool_destroy_work_item(threadpool, threadpool_work_item); - threadpool_close(threadpool); + threadpool_destroy_work_item(threadpool, threadpool_work_item); (void)interlocked_exchange(&thread_counter, 0); - // Reopen the threadpool - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - threadpool_work_item = threadpool_create_work_item(threadpool, threadpool_task_wait_20_millisec, (void*)&thread_counter); ASSERT_IS_NOT_NULL(threadpool_work_item); @@ -860,13 +826,12 @@ TEST_FUNCTION(schedule_after_close_works) ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); // cleanup - threadpool_destroy_work_item(threadpool, threadpool_work_item); - threadpool_close(threadpool); + threadpool_destroy_work_item(threadpool, threadpool_work_item); THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } -TEST_FUNCTION(schedule_after_close_works_v2) +TEST_FUNCTION(schedule_work_two_times_v2) { // assert EXECUTION_ENGINE_PARAMETERS params; @@ -880,27 +845,18 @@ TEST_FUNCTION(schedule_after_close_works_v2) THANDLE(THREADPOOL) threadpool = threadpool_create(execution_engine); ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - // Create 1 thread pool LogInfo("Scheduling work item"); ASSERT_ARE_EQUAL(int, 0, threadpool_schedule_work(threadpool, threadpool_task_wait_20_millisec, (void*)&thread_counter)); // assert LogInfo("Waiting for task to complete"); - do - { - (void)InterlockedHL_WaitForValue(&thread_counter, num_threads, TEST_TIMEOUT_VALUE); - } while (interlocked_add(&thread_counter, 0) != num_threads); + ASSERT_ARE_EQUAL(int, INTERLOCKED_HL_OK, InterlockedHL_WaitForValue(&thread_counter, num_threads, UINT32_MAX)); ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); - threadpool_close(threadpool); (void)interlocked_exchange(&thread_counter, 0); - // Reopen the threadpool - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - // Create 1 thread pool LogInfo("Scheduling work item"); ASSERT_ARE_EQUAL(int, 0, threadpool_schedule_work(threadpool, threadpool_task_wait_20_millisec, (void*)&thread_counter)); @@ -912,7 +868,6 @@ TEST_FUNCTION(schedule_after_close_works_v2) ASSERT_ARE_EQUAL(int32_t, thread_counter, num_threads, "Thread counter has timed out"); // cleanup - threadpool_close(threadpool); THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); execution_engine_dec_ref(execution_engine); } diff --git a/linux/tests/threadpool_linux_ut/threadpool_linux_ut.c b/linux/tests/threadpool_linux_ut/threadpool_linux_ut.c index 149e3e9f..ec49af63 100644 --- a/linux/tests/threadpool_linux_ut/threadpool_linux_ut.c +++ b/linux/tests/threadpool_linux_ut/threadpool_linux_ut.c @@ -71,10 +71,6 @@ THREADAPI_RESULT my_ThreadAPI_Create(THREAD_HANDLE* threadHandle, THREAD_START_F MU_DEFINE_ENUM_STRINGS(UMOCK_C_ERROR_CODE, UMOCK_C_ERROR_CODE_VALUES) -MU_DEFINE_ENUM_STRINGS(SM_RESULT, SM_RESULT_VALUES); -TEST_DEFINE_ENUM_TYPE(SM_RESULT, SM_RESULT_VALUES); -IMPLEMENT_UMOCK_C_ENUM_TYPE(SM_RESULT, SM_RESULT_VALUES); - MU_DEFINE_ENUM_STRINGS(INTERLOCKED_HL_RESULT, INTERLOCKED_HL_RESULT_VALUES); TEST_DEFINE_ENUM_TYPE(INTERLOCKED_HL_RESULT, INTERLOCKED_HL_RESULT_VALUES); IMPLEMENT_UMOCK_C_ENUM_TYPE(INTERLOCKED_HL_RESULT, INTERLOCKED_HL_RESULT_VALUES); @@ -122,8 +118,7 @@ MOCK_FUNCTION_END(0) static void threadpool_create_succeed_expectations(void) { STRICT_EXPECTED_CALL(malloc(IGNORED_ARG)); - STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_create(IGNORED_ARG)); + STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(execution_engine_linux_get_parameters(test_execution_engine)); STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(malloc_2(DEFAULT_TASK_ARRAY_SIZE, IGNORED_ARG)); @@ -137,11 +132,15 @@ static void threadpool_create_succeed_expectations(void) STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_exchange_64(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_exchange_64(IGNORED_ARG, 0)); + + for(size_t i = 0; i < MIN_THREAD_COUNT; i++) + { + STRICT_EXPECTED_CALL(ThreadAPI_Create(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); + } } static void threadpool_schedule_work_succeed_expectations(void) -{ - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); +{ STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_increment_64(IGNORED_ARG)); @@ -149,24 +148,17 @@ static void threadpool_schedule_work_succeed_expectations(void) STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(mocked_sem_post(IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); } static void threadpool_create_work_item_success_expectations(void) { - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); STRICT_EXPECTED_CALL(malloc(IGNORED_ARG)); - STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); } static void threadpool_destroy_work_item_succeed_expectations(void) -{ - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); +{ STRICT_EXPECTED_CALL(InterlockedHL_WaitForValue(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)).SetReturn(INTERLOCKED_HL_OK); - STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(free(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); } static void threadpool_task(void* parameter) @@ -177,13 +169,10 @@ static void threadpool_task(void* parameter) wake_by_address_single(thread_counter); } -static THANDLE(THREADPOOL) test_create_and_open_threadpool(void) +static THANDLE(THREADPOOL) test_create_threadpool(void) { THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_IS_NOT_NULL(threadpool); - umock_c_reset_all_calls(); - - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); + ASSERT_IS_NOT_NULL(threadpool); umock_c_reset_all_calls(); return threadpool; @@ -191,7 +180,7 @@ static THANDLE(THREADPOOL) test_create_and_open_threadpool(void) static void test_create_threadpool_and_start_timer(uint32_t start_delay_ms, uint32_t timer_period_ms, void* work_function_context, THANDLE(THREADPOOL)* threadpool, TIMER_INSTANCE_HANDLE* timer_instance) { - THANDLE(THREADPOOL) test_result = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) test_result = test_create_threadpool(); STRICT_EXPECTED_CALL(malloc(IGNORED_ARG)); STRICT_EXPECTED_CALL(mocked_timer_create(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); @@ -217,8 +206,7 @@ TEST_SUITE_INITIALIZE(suite_init) REGISTER_UMOCK_ALIAS_TYPE(SRW_LOCK_HANDLE, void*); REGISTER_UMOCK_ALIAS_TYPE(THREADAPI_RESULT, int); REGISTER_UMOCK_ALIAS_TYPE(clockid_t, int); - REGISTER_UMOCK_ALIAS_TYPE(timer_t, void*); - REGISTER_UMOCK_ALIAS_TYPE(SM_HANDLE, void*); + REGISTER_UMOCK_ALIAS_TYPE(timer_t, void*); REGISTER_GLOBAL_MOCK_RETURN(execution_engine_linux_get_parameters, &execution_engine); REGISTER_GLOBAL_MOCK_RETURNS(srw_lock_create, test_srw_lock, NULL); @@ -230,17 +218,13 @@ TEST_SUITE_INITIALIZE(suite_init) REGISTER_GBALLOC_HL_GLOBAL_MOCK_HOOK(); REGISTER_INTERLOCKED_GLOBAL_MOCK_HOOK(); - REGISTER_INTERLOCKED_HL_GLOBAL_MOCK_HOOK(); - REGISTER_SM_GLOBAL_MOCK_HOOK(); + REGISTER_INTERLOCKED_HL_GLOBAL_MOCK_HOOK(); REGISTER_GLOBAL_MOCK_FAIL_RETURN(malloc, NULL); REGISTER_GLOBAL_MOCK_FAIL_RETURN(malloc_2, NULL); REGISTER_GLOBAL_MOCK_RETURNS(mocked_timer_create, 0, 1); REGISTER_GLOBAL_MOCK_RETURNS(mocked_timer_settime, 0, -1); - REGISTER_TYPE(SM_RESULT, SM_RESULT); REGISTER_TYPE(INTERLOCKED_HL_RESULT, INTERLOCKED_HL_RESULT); - - REGISTER_UMOCKC_PAIRED_CREATE_DESTROY_CALLS(sm_create, sm_destroy); } TEST_SUITE_CLEANUP(suite_cleanup) @@ -280,7 +264,6 @@ TEST_FUNCTION(threadpool_create_with_NULL_execution_engine_fails) /* Tests_SRS_THREADPOOL_LINUX_07_001: [ threadpool_create shall allocate memory for a threadpool object and on success return a non-NULL handle to it. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_004: [ threadpool_create shall get the min_thread_count and max_thread_count thread parameters from the execution_engine. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_005: [ threadpool_create shall allocate memory for an array of thread handles of size min_thread_count and on success return a non-NULL handle to it. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_003: [ threadpool_create shall create a SM_HANDLE by calling sm_create. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_006: [ threadpool_create shall allocate memory with default task array size 2048 for an array of tasks and on success return a non-NULL handle to it. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_007: [ threadpool_create shall initialize every task item in the tasks array with task_func and task_param set to NULL and task_state set to TASK_NOT_USED. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_009: [ threadpool_create shall create a shared semaphore with initialized value zero. ]*/ @@ -310,7 +293,6 @@ TEST_FUNCTION(when_underlying_calls_fail_threadpool_create_also_fails) STRICT_EXPECTED_CALL(malloc(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)) .CallCannotFail(); - STRICT_EXPECTED_CALL(sm_create(IGNORED_ARG)); STRICT_EXPECTED_CALL(execution_engine_linux_get_parameters(test_execution_engine)) .CallCannotFail(); STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, IGNORED_ARG)); @@ -344,7 +326,6 @@ TEST_FUNCTION(when_underlying_calls_fail_threadpool_create_also_fails) /* Tests_SRS_THREADPOOL_LINUX_07_001: [ threadpool_create shall allocate memory for a threadpool object and on success return a non-NULL handle to it. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_004: [ threadpool_create shall get the min_thread_count and max_thread_count thread parameters from the execution_engine. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_005: [ threadpool_create shall allocate memory for an array of thread handles of size min_thread_count and on success return a non-NULL handle to it. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_003: [ threadpool_create shall create a SM_HANDLE by calling sm_create. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_006: [ threadpool_create shall allocate memory with default task array size 2048 for an array of tasks and on success return a non-NULL handle to it. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_007: [ threadpool_create shall initialize every task item in the tasks array with task_func and task_param set to NULL and task_state set to TASK_NOT_USED. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_009: [ threadpool_create shall create a shared semaphore with initialized value zero. ]*/ @@ -357,8 +338,8 @@ TEST_FUNCTION(creating_2_threadpool_succeeds) threadpool_create_succeed_expectations(); // act - THANDLE(THREADPOOL) threadpool_1 = threadpool_create(test_execution_engine); - THANDLE(THREADPOOL) threadpool_2 = threadpool_create(test_execution_engine); + THANDLE(THREADPOOL) threadpool_1 = test_create_threadpool(); + THANDLE(THREADPOOL) threadpool_2 = test_create_threadpool(); // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); @@ -371,24 +352,26 @@ TEST_FUNCTION(creating_2_threadpool_succeeds) THANDLE_ASSIGN(THREADPOOL)(&threadpool_2, NULL); } -/* threadpool_destroy */ +/* threadpool_dispose */ -/* Tests_SRS_THREADPOOL_LINUX_07_016: [ threadpool_destroy shall free the memory allocated in threadpool_create. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_014: [ threadpool_destroy shall destroy the semphore by calling sem_destroy. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_015: [ threadpool_destroy shall destroy the SRW lock by calling srw_lock_destroy. ]*/ -TEST_FUNCTION(threadpool_destroy_frees_resources) +/* Tests_SRS_THREADPOOL_LINUX_07_016: [ threadpool_dispose shall free the memory allocated in threadpool_create. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_014: [ threadpool_dispose shall destroy the semphore by calling sem_destroy. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_015: [ threadpool_dispose shall destroy the SRW lock by calling srw_lock_destroy. ]*/ +TEST_FUNCTION(threadpool_dispose_frees_resources) { // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - umock_c_reset_all_calls(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_close_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(InterlockedHL_SetAndWakeAll(IGNORED_ARG, IGNORED_ARG)); + for(size_t i = 0; i < MIN_THREAD_COUNT; i++) + { + STRICT_EXPECTED_CALL(ThreadAPI_Join(IGNORED_ARG, IGNORED_ARG)); + } STRICT_EXPECTED_CALL(free(IGNORED_ARG)); STRICT_EXPECTED_CALL(free(IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_destroy(IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_destroy(IGNORED_ARG)); STRICT_EXPECTED_CALL(free(IGNORED_ARG)); // act @@ -396,31 +379,27 @@ TEST_FUNCTION(threadpool_destroy_frees_resources) // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_IS_NULL(threadpool); } -/* Tests_SRS_THREADPOOL_LINUX_07_013: [ threadpool_destroy shall perform an implicit close if threadpool is open. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_016: [ threadpool_destroy shall free the memory allocated in threadpool_create. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_014: [ threadpool_destroy shall destroy the semphore by calling sem_destroy. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_015: [ threadpool_destroy shall destroy the SRW lock by calling srw_lock_destroy. ]*/ -TEST_FUNCTION(threadpool_destroy_performs_an_implicit_close) +/* Tests_SRS_THREADPOOL_LINUX_07_016: [ threadpool_dispose shall free the memory allocated in threadpool_create. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_014: [ threadpool_dispose shall destroy the semphore by calling sem_destroy. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_015: [ threadpool_dispose shall destroy the SRW lock by calling srw_lock_destroy. ]*/ +TEST_FUNCTION(threadpool_dispose_performs_an_implicit_close) { // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - umock_c_reset_all_calls(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_close_begin(IGNORED_ARG)); + STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG)); STRICT_EXPECTED_CALL(InterlockedHL_SetAndWakeAll(IGNORED_ARG, 1)); for(size_t i = 0; i < MIN_THREAD_COUNT; i++) { STRICT_EXPECTED_CALL(ThreadAPI_Join(IGNORED_ARG, IGNORED_ARG)); } - STRICT_EXPECTED_CALL(sm_close_end(IGNORED_ARG)); STRICT_EXPECTED_CALL(free(IGNORED_ARG)); STRICT_EXPECTED_CALL(free(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_destroy(IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_destroy(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_destroy(IGNORED_ARG)); STRICT_EXPECTED_CALL(free(IGNORED_ARG)); // act @@ -428,6 +407,47 @@ TEST_FUNCTION(threadpool_destroy_performs_an_implicit_close) // assert ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + ASSERT_IS_NULL(threadpool); +} + +/* Tests_SRS_THREADPOOL_LINUX_07_020: [ threadpool_create shall create number of min_thread_count threads for threadpool using ThreadAPI_Create. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_022: [ If one of the thread creation fails, threadpool_create shall fail and return a non-zero value, terminate all threads already created. ]*/ +TEST_FUNCTION(threadpool_create_fails_when_threadAPI_create_fails) +{ + // arrange + + STRICT_EXPECTED_CALL(malloc(IGNORED_ARG)); + STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); + STRICT_EXPECTED_CALL(execution_engine_linux_get_parameters(test_execution_engine)); + STRICT_EXPECTED_CALL(malloc_2(IGNORED_ARG, IGNORED_ARG)); + STRICT_EXPECTED_CALL(malloc_2(DEFAULT_TASK_ARRAY_SIZE, IGNORED_ARG)); + for (int32_t i = 0; i < DEFAULT_TASK_ARRAY_SIZE; i++) + { + STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); + } + STRICT_EXPECTED_CALL(srw_lock_create(false, IGNORED_ARG)).SetReturn(test_srw_lock); + STRICT_EXPECTED_CALL(mocked_sem_init(IGNORED_ARG, 0, 0)); + STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, 0)); + STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, 0)); + STRICT_EXPECTED_CALL(interlocked_exchange_64(IGNORED_ARG, 0)); + STRICT_EXPECTED_CALL(interlocked_exchange_64(IGNORED_ARG, 0)); + + STRICT_EXPECTED_CALL(ThreadAPI_Create(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); + STRICT_EXPECTED_CALL(ThreadAPI_Create(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)) + .SetReturn(THREADAPI_ERROR); + STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, 1)); + STRICT_EXPECTED_CALL(ThreadAPI_Join(IGNORED_ARG, IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_destroy(IGNORED_ARG)); + STRICT_EXPECTED_CALL(free(IGNORED_ARG)); + STRICT_EXPECTED_CALL(free(IGNORED_ARG)); + STRICT_EXPECTED_CALL(free(IGNORED_ARG)); + + // act + THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); + ASSERT_IS_NULL(threadpool); + + // assert + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* threadpool_open */ @@ -446,35 +466,18 @@ TEST_FUNCTION(threadpool_open_with_NULL_threadpool_fails) ASSERT_ARE_NOT_EQUAL(int, 0, result); } -/* Tests_SRS_THREADPOOL_LINUX_07_018: [ threadpool_open shall call sm_open_begin. ]*/ -// Tests_SRS_THREADPOOL_LINUX_11_001: [ threadpool_open shall initialize internal threapool data items ] -/* Tests_SRS_THREADPOOL_LINUX_07_020: [ threadpool_open shall create number of min_thread_count threads for threadpool using ThreadAPI_Create. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_023: [ Otherwise, threadpool_open shall shall call sm_open_end with true for success. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_024: [ threadpool_open shall succeed, indicate open success to the user by calling the on_open_complete callback with THREADPOOL_OPEN_OK and return zero. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_020: [ threadpool_create shall create number of min_thread_count threads for threadpool using ThreadAPI_Create. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_024: [ Otherwise, threadpool_open shall succeed and return 0. ]*/ TEST_FUNCTION(threadpool_open_succeeds) { // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - int result; - umock_c_reset_all_calls(); + int result; - STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG)); - STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); - for (int32_t i = 0; i < DEFAULT_TASK_ARRAY_SIZE; i++) - { - STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); - } - STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); - STRICT_EXPECTED_CALL(interlocked_exchange_64(IGNORED_ARG, 0)); - STRICT_EXPECTED_CALL(interlocked_exchange_64(IGNORED_ARG, 0)); - - for(size_t i = 0; i < MIN_THREAD_COUNT; i++) - { - STRICT_EXPECTED_CALL(ThreadAPI_Create(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); - } - STRICT_EXPECTED_CALL(sm_open_end(IGNORED_ARG, true)); + threadpool_create_succeed_expectations(); // act + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + result = threadpool_open(threadpool); // assert @@ -485,14 +488,13 @@ TEST_FUNCTION(threadpool_open_succeeds) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } +/* threadpool_work_func */ + /* Tests_SRS_THREADPOOL_LINUX_07_073: [ If param is NULL, threadpool_work_func shall fail and return. ]*/ TEST_FUNCTION(threadpool_work_func_parameter_NULL_succeeds) { //arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - umock_c_reset_all_calls(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); //act g_saved_worker_thread_func(NULL); @@ -509,11 +511,8 @@ TEST_FUNCTION(threadpool_work_func_parameter_NULL_succeeds) TEST_FUNCTION(threadpool_work_func_succeeds_when_clock_gettime_fails) { //arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - umock_c_reset_all_calls(); - + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + STRICT_EXPECTED_CALL(mocked_clock_gettime(CLOCK_REALTIME, IGNORED_ARG)).SetReturn(-1); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)).SetReturn(1); @@ -531,10 +530,7 @@ TEST_FUNCTION(threadpool_work_func_succeeds_when_clock_gettime_fails) TEST_FUNCTION(threadpool_work_func_succeeds_when_sem_timedwait_fails) { //arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - umock_c_reset_all_calls(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); STRICT_EXPECTED_CALL(mocked_clock_gettime(CLOCK_REALTIME, IGNORED_ARG)); STRICT_EXPECTED_CALL(mocked_sem_timedwait(IGNORED_ARG, IGNORED_ARG)).SetReturn(1); @@ -561,15 +557,12 @@ TEST_FUNCTION(threadpool_work_func_succeeds_when_sem_timedwait_fails) /* Tests_SRS_THREADPOOL_LINUX_07_082: [ threadpool_work_func shall set the task state to TASK_NOT_USED. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_083: [ threadpool_work_func shall release the shared SRW lock by calling srw_lock_release_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_084: [ If the work item function is not NULL, threadpool_work_func shall execute it with work_function_ctx. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_039: [ threadpool_work_func shall acquire the shared SRW lock by calling srw_lock_acquire_shared. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_041: [ threadpool_work_func shall release the shared SRW lock by calling srw_lock_release_shared. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_085: [ threadpool_work_func shall loop until threadpool_close or threadpool_destroy is called. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_085: [ threadpool_work_func shall loop until the flag to stop the threads is not set to 1. ]*/ TEST_FUNCTION(threadpool_work_func_succeeds_for_threadpool_schedule_work) { //arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + threadpool_schedule_work(threadpool, test_work_function, (void*)0x4242); umock_c_reset_all_calls(); @@ -582,8 +575,8 @@ TEST_FUNCTION(threadpool_work_func_succeeds_for_threadpool_schedule_work) STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(test_work_function(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_acquire_exclusive(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_release_exclusive(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)).SetReturn(1); //act @@ -607,21 +600,11 @@ TEST_FUNCTION(threadpool_work_func_succeeds_for_threadpool_schedule_work) /* Tests_SRS_THREADPOOL_LINUX_07_082: [ threadpool_work_func shall set the task state to TASK_NOT_USED. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_083: [ threadpool_work_func shall release the shared SRW lock by calling srw_lock_release_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_084: [ If the work item function is not NULL, threadpool_work_func shall execute it with work_function_ctx. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_039: [ threadpool_work_func shall acquire the shared SRW lock by calling srw_lock_acquire_shared. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_040: [ threadpool_work_func shall save pending_work_item_count_ptr is not NULL in is_pending_work_item_count_ptr_not_null. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_041: [ threadpool_work_func shall release the shared SRW lock by calling srw_lock_release_shared. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_042: [ If the is_pending_work_item_count_ptr_not_null is TRUE then: ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_043: [ threadpool_work_func shall acquire the exclusive SRW lock by calling srw_lock_acquire_exclusive. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_044: [ threadpool_work_func shall decrement the pending_work_item_count_ptr by calling interlocked_decrement. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_045: [ threadpool_work_func shall send wake up signal to single listener for the address in pending_work_item_count_ptr. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_046: [ threadpool_work_func shall release the shared SRW lock by calling srw_lock_release_exclusive. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_085: [ threadpool_work_func shall loop until threadpool_close or threadpool_destroy is called. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_085: [ threadpool_work_func shall loop until the flag to stop the threads is not set to 1. ]*/ TEST_FUNCTION(threadpool_work_func_succeeds_for_threadpool_schedule_work_item) { //arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_IS_NOT_NULL(threadpool); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item = threadpool_create_work_item(threadpool, test_work_function, (void*)0x4242); threadpool_schedule_work_item(threadpool, threadpool_work_item); umock_c_reset_all_calls(); @@ -634,9 +617,7 @@ TEST_FUNCTION(threadpool_work_func_succeeds_for_threadpool_schedule_work_item) STRICT_EXPECTED_CALL(interlocked_compare_exchange(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); - STRICT_EXPECTED_CALL(test_work_function(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); + STRICT_EXPECTED_CALL(test_work_function(IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_acquire_exclusive(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG)); STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG)); @@ -654,66 +635,6 @@ TEST_FUNCTION(threadpool_work_func_succeeds_for_threadpool_schedule_work_item) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_07_018: [ threadpool_open shall call sm_open_begin. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_020: [ threadpool_open shall create number of min_thread_count threads for threadpool using ThreadAPI_Create. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_022: [ If one of the thread creation fails, threadpool_open shall fail and return a non-zero value, terminate all threads already created. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_021: [ If any error occurs, threadpool_open shall fail and return a non-zero value. ]*/ -TEST_FUNCTION(threadpool_open_fails_when_threadAPI_create_fails) -{ - // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - int result; - umock_c_reset_all_calls(); - - STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG)); - STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); - for (int32_t i = 0; i < DEFAULT_TASK_ARRAY_SIZE; i++) - { - STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); - } - STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, 0)); - STRICT_EXPECTED_CALL(interlocked_exchange_64(IGNORED_ARG, 0)); - STRICT_EXPECTED_CALL(interlocked_exchange_64(IGNORED_ARG, 0)); - - STRICT_EXPECTED_CALL(ThreadAPI_Create(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); - STRICT_EXPECTED_CALL(ThreadAPI_Create(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)) - .SetReturn(THREADAPI_ERROR); - STRICT_EXPECTED_CALL(ThreadAPI_Join(IGNORED_ARG, IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_open_end(IGNORED_ARG, false)); - - // act - result = threadpool_open(threadpool); - - // assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_ARE_NOT_EQUAL(int, 0, result); - - // cleanup - THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); -} - -/* Tests_SRS_THREADPOOL_LINUX_07_018: [ threadpool_open shall call sm_open_begin. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_019: [ If sm_open_begin indicates the open cannot be performed, threadpool_open shall fail and return a non-zero value. ]*/ -TEST_FUNCTION(threadpool_open_after_open_fails) -{ - // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - int result; - umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(sm_open_begin(IGNORED_ARG)); - - // act - result = threadpool_open(threadpool); - - // assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_ARE_NOT_EQUAL(int, 0, result); - - // cleanup - THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); -} - /* threadpool_close */ /* Tests_SRS_THREADPOOL_LINUX_07_025: [ If threadpool is NULL, threadpool_close shall fail and return. ]*/ @@ -728,72 +649,29 @@ TEST_FUNCTION(threadpool_close_with_NULL_handle_returns) ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } -/* Tests_SRS_THREADPOOL_LINUX_07_026: [ Otherwise, threadpool_close shall call sm_close_begin. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_089: [ threadpool_close shall signal all threads threadpool is closing by calling InterlockedHL_SetAndWakeAll. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_027: [ threadpool_close shall join all threads in the threadpool. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_028: [ threadpool_close shall call sm_close_end. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_089: [ threadpool_dispose shall signal all threads to return. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_07_027: [ threadpool_dispose shall join all threads in the threadpool. ]*/ TEST_FUNCTION(threadpool_close_succeeds) { // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - umock_c_reset_all_calls(); - - STRICT_EXPECTED_CALL(sm_close_begin(IGNORED_ARG)); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + + STRICT_EXPECTED_CALL(interlocked_decrement(IGNORED_ARG)); STRICT_EXPECTED_CALL(InterlockedHL_SetAndWakeAll(IGNORED_ARG, IGNORED_ARG)); for(size_t i = 0; i < MIN_THREAD_COUNT; i++) { STRICT_EXPECTED_CALL(ThreadAPI_Join(IGNORED_ARG, IGNORED_ARG)); - } - STRICT_EXPECTED_CALL(sm_close_end(IGNORED_ARG)); - - // act - threadpool_close(threadpool); - - // assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - // cleanup - THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); -} - -/* Tests_SRS_THREADPOOL_LINUX_07_026: [ Otherwise, threadpool_close shall call sm_close_begin. ]*/ -TEST_FUNCTION(threadpool_close_when_not_open_returns) -{ - // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(sm_close_begin(IGNORED_ARG)); + } + STRICT_EXPECTED_CALL(free(IGNORED_ARG)); + STRICT_EXPECTED_CALL(free(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_destroy(IGNORED_ARG)); + STRICT_EXPECTED_CALL(free(IGNORED_ARG)); // act - threadpool_close(threadpool); - - // assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - // cleanup THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); -} - -/* Tests_SRS_THREADPOOL_LINUX_07_026: [ Otherwise, threadpool_close shall call sm_close_begin. ]*/ -TEST_FUNCTION(threadpool_close_after_close_returns) -{ - // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - ASSERT_ARE_EQUAL(int, 0, threadpool_open(threadpool)); - threadpool_close(threadpool); - umock_c_reset_all_calls(); - - STRICT_EXPECTED_CALL(sm_close_begin(IGNORED_ARG)); - - // act - threadpool_close(threadpool); // assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - // cleanup - THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); } /* threadpool_schedule_work */ @@ -816,10 +694,9 @@ TEST_FUNCTION(threadpool_schedule_work_with_NULL_threadpool_fails) TEST_FUNCTION(threadpool_schedule_work_with_NULL_work_function_fails) { // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); int result; - umock_c_reset_all_calls(); - + // act result = threadpool_schedule_work(threadpool, NULL, (void*)0x4243); @@ -831,7 +708,6 @@ TEST_FUNCTION(threadpool_schedule_work_with_NULL_work_function_fails) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_07_031: [ threadpool_schedule_work shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_033: [ threadpool_schedule_work shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_034: [ threadpool_schedule_work shall increment the insert_pos. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_035: [ If task state is TASK_NOT_USED, threadpool_schedule_work shall set the current task state to TASK_INITIALIZING. ]*/ @@ -839,11 +715,10 @@ TEST_FUNCTION(threadpool_schedule_work_with_NULL_work_function_fails) /* Tests_SRS_THREADPOOL_LINUX_07_050: [ threadpool_schedule_work shall set the task_state to TASK_WAITING and then release the shared SRW lock. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_051: [ threadpool_schedule_work shall unblock the threadpool semaphore by calling sem_post. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_047: [ threadpool_schedule_work shall return zero on success. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_053: [ threadpool_schedule_work shall call sm_exec_end. ]*/ TEST_FUNCTION(threadpool_schedule_work_succeeds) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); int result; threadpool_schedule_work_succeed_expectations(); @@ -860,7 +735,6 @@ TEST_FUNCTION(threadpool_schedule_work_succeeds) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_07_031: [ threadpool_schedule_work shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_033: [ threadpool_schedule_work shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_034: [ threadpool_schedule_work shall increment the insert_pos. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_035: [ If task state is TASK_NOT_USED, threadpool_schedule_work shall set the current task state to TASK_INITIALIZING. ]*/ @@ -868,11 +742,10 @@ TEST_FUNCTION(threadpool_schedule_work_succeeds) /* Tests_SRS_THREADPOOL_LINUX_07_050: [ threadpool_schedule_work shall set the task_state to TASK_WAITING and then release the shared SRW lock. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_051: [ threadpool_schedule_work shall unblock the threadpool semaphore by calling sem_post. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_047: [ threadpool_schedule_work shall return zero on success. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_053: [ threadpool_schedule_work shall call sm_exec_end. ]*/ TEST_FUNCTION(threadpool_schedule_work_succeeds_with_NULL_work_function_context) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); int result; threadpool_schedule_work_succeed_expectations(); @@ -889,29 +762,6 @@ TEST_FUNCTION(threadpool_schedule_work_succeeds_with_NULL_work_function_context) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_07_031: [ threadpool_schedule_work shall call sm_exec_begin. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_07_032: [ If sm_exec_begin returns SM_EXEC_REFUSED, threadpool_schedule_work shall fail and return a non-zero value. ]*/ -TEST_FUNCTION(threadpool_schedule_work_fails_when_threadpool_not_open) -{ - // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - int result; - umock_c_reset_all_calls(); - - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); - - // act - result = threadpool_schedule_work(threadpool, test_work_function, (void*)0x4243); - - // assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_ARE_NOT_EQUAL(int, 0, result); - - // cleanup - THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); -} - -/* Tests_SRS_THREADPOOL_LINUX_07_031: [ threadpool_schedule_work shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_033: [ threadpool_schedule_work shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_034: [ threadpool_schedule_work shall increment the insert_pos. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_035: [ If task state is TASK_NOT_USED, threadpool_schedule_work shall set the current task state to TASK_INITIALIZING. ]*/ @@ -927,11 +777,9 @@ TEST_FUNCTION(threadpool_schedule_work_fails_when_threadpool_not_open) TEST_FUNCTION(threadpool_schedule_work_realloc_array_with_no_empty_space) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); int result; - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_increment_64(IGNORED_ARG)); @@ -956,8 +804,6 @@ TEST_FUNCTION(threadpool_schedule_work_realloc_array_with_no_empty_space) STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(mocked_sem_post(IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); - // act result = threadpool_schedule_work(threadpool, test_work_function, (void*)0x4243); @@ -968,7 +814,7 @@ TEST_FUNCTION(threadpool_schedule_work_realloc_array_with_no_empty_space) // cleanup THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_07_031: [ threadpool_schedule_work shall call sm_exec_begin. ]*/ + /* Tests_SRS_THREADPOOL_LINUX_07_033: [ threadpool_schedule_work shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_034: [ threadpool_schedule_work shall increment the insert_pos. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_035: [ If task state is TASK_NOT_USED, threadpool_schedule_work shall set the current task state to TASK_INITIALIZING. ]*/ @@ -979,11 +825,9 @@ TEST_FUNCTION(threadpool_schedule_work_realloc_array_with_no_empty_space) TEST_FUNCTION(threadpool_schedule_work_fails_when_new_array_size_overflows) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); int result; - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_increment_64(IGNORED_ARG)); @@ -992,9 +836,7 @@ TEST_FUNCTION(threadpool_schedule_work_fails_when_new_array_size_overflows) STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_acquire_exclusive(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)).SetReturn(INT32_MAX/2+1); - STRICT_EXPECTED_CALL(srw_lock_release_exclusive(IGNORED_ARG)); - - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_release_exclusive(IGNORED_ARG)); // act result = threadpool_schedule_work(threadpool, test_work_function, (void*)0x4243); @@ -1007,7 +849,6 @@ TEST_FUNCTION(threadpool_schedule_work_fails_when_new_array_size_overflows) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_07_031: [ threadpool_schedule_work shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_033: [ threadpool_schedule_work shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_034: [ threadpool_schedule_work shall increment the insert_pos. ]*/ /* Tests_SRS_THREADPOOL_LINUX_07_035: [ If task state is TASK_NOT_USED, threadpool_schedule_work shall set the current task state to TASK_INITIALIZING. ]*/ @@ -1017,11 +858,9 @@ TEST_FUNCTION(threadpool_schedule_work_fails_when_new_array_size_overflows) TEST_FUNCTION(threadpool_schedule_work_fails_when_realloc_array_fails) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); int result; - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_increment_64(IGNORED_ARG)); @@ -1033,9 +872,7 @@ TEST_FUNCTION(threadpool_schedule_work_fails_when_realloc_array_fails) STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(realloc_2(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)).SetReturn(NULL); STRICT_EXPECTED_CALL(srw_lock_release_exclusive(IGNORED_ARG)); - - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); - + // act result = threadpool_schedule_work(threadpool, test_work_function, (void*)0x4243); @@ -1067,7 +904,7 @@ TEST_FUNCTION(threadpool_timer_start_with_NULL_threadpool_fails) TEST_FUNCTION(threadpool_timer_start_with_NULL_work_function_fails) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); TIMER_INSTANCE_HANDLE timer_instance; // act @@ -1085,7 +922,7 @@ TEST_FUNCTION(threadpool_timer_start_with_NULL_work_function_fails) TEST_FUNCTION(threadpool_timer_start_with_NULL_timer_handle_fails) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); // act int result = threadpool_timer_start(threadpool, 42, 2000, test_work_function, (void*)0x4243, NULL); @@ -1107,7 +944,7 @@ TEST_FUNCTION(threadpool_timer_start_with_NULL_timer_handle_fails) TEST_FUNCTION(threadpool_timer_start_succeeds) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); TIMER_INSTANCE_HANDLE timer_instance; @@ -1138,7 +975,7 @@ TEST_FUNCTION(threadpool_timer_start_succeeds) TEST_FUNCTION(threadpool_timer_start_with_NULL_work_function_context_succeeds) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); TIMER_INSTANCE_HANDLE timer_instance; @@ -1168,7 +1005,7 @@ TEST_FUNCTION(threadpool_timer_start_with_NULL_work_function_context_succeeds) TEST_FUNCTION(threadpool_timer_start_delete_timer_when_timer_set_time_functions_fails) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); TIMER_INSTANCE_HANDLE timer_instance; @@ -1194,7 +1031,7 @@ TEST_FUNCTION(threadpool_timer_start_delete_timer_when_timer_set_time_functions_ TEST_FUNCTION(threadpool_timer_start_fails_when_underlying_functions_fail) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); TIMER_INSTANCE_HANDLE timer_instance; STRICT_EXPECTED_CALL(malloc(IGNORED_ARG)); @@ -1372,7 +1209,7 @@ TEST_FUNCTION(threadpool_timer_destroy_succeeds) TEST_FUNCTION(on_timer_callback_calls_work_function) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); TIMER_INSTANCE_HANDLE timer_instance; STRICT_EXPECTED_CALL(malloc(IGNORED_ARG)); @@ -1409,7 +1246,7 @@ TEST_FUNCTION(on_timer_callback_calls_work_function) TEST_FUNCTION(on_timer_callback_does_nothing_with_null_pointer) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); TIMER_INSTANCE_HANDLE timer_instance; STRICT_EXPECTED_CALL(malloc(IGNORED_ARG)); @@ -1438,7 +1275,7 @@ TEST_FUNCTION(on_timer_callback_does_nothing_with_null_pointer) /* threadpool_create_work_item */ -/* Tests_SRS_THREADPOOL_LINUX_05_001: [ If threadpool is NULL, threadpool_create_work_item shall fail and set the return variable threadpool_work_item a NULL value. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_001: [ If threadpool is NULL, threadpool_create_work_item shall fail and return a NULL value. ]*/ TEST_FUNCTION(threadpool_create_work_item_with_NULL_threadpool_fails) { @@ -1453,15 +1290,14 @@ TEST_FUNCTION(threadpool_create_work_item_with_NULL_threadpool_fails) ASSERT_IS_NULL(threadpool_work_item); } -/* Tests_SRS_THREADPOOL_LINUX_05_002: [ If work_function is NULL, threadpool_create_work_item shall fail and set the return variable threadpool_work_item a NULL value. ] */ +/* Tests_SRS_THREADPOOL_LINUX_05_002: [ If work_function is NULL, threadpool_create_work_item shall fail and return a NULL value. ] */ TEST_FUNCTION(threadpool_create_work_item_with_NULL_work_function_fails) { // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; - umock_c_reset_all_calls(); - + // act threadpool_work_item = threadpool_create_work_item(threadpool, NULL, (void*)0x4243); @@ -1472,18 +1308,15 @@ TEST_FUNCTION(threadpool_create_work_item_with_NULL_work_function_fails) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_05_003: [ threadpool_create_work_item shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_005: [ threadpool_create_work_item shall allocate memory for threadpool_work_item of type THREADPOOL_WORK_ITEM_HANDLE. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_007: [ threadpool_create_work_item shall initialize pending_work_item_count to 0 then copy the work_function and work_function_context into the threadpool_work_item and an initialized threadpool_work_item when returned indicates success. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_008: [ threadpool_create_work_item shall call sm_exec_end. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_009: [ Return the value inside threadpool_work_item ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_007: [ threadpool_create_work_item shall copy the work_function and work_function_context into the threadpool work item. ]*/ TEST_FUNCTION(threadpool_create_work_item_succeeds) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; - umock_c_reset_all_calls(); + threadpool_create_work_item_success_expectations(); // act @@ -1501,18 +1334,15 @@ TEST_FUNCTION(threadpool_create_work_item_succeeds) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_05_003: [ threadpool_create_work_item shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_005: [ threadpool_create_work_item shall allocate memory for threadpool_work_item of type THREADPOOL_WORK_ITEM_HANDLE. ] */ -/* Tests_SRS_THREADPOOL_LINUX_05_007: [ threadpool_create_work_item shall initialize pending_work_item_count to 0 then copy the work_function and work_function_context into the threadpool_work_item and an initialized threadpool_work_item when returned indicates success. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_008: [ threadpool_create_work_item shall call sm_exec_end. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_009: [ Return the value inside threadpool_work_item ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_007: [ threadpool_create_work_item shall copy the work_function and work_function_context into the threadpool work item. ]*/ TEST_FUNCTION(threadpool_create_work_item_succeeds_with_NULL_work_function_context) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; - umock_c_reset_all_calls(); + threadpool_create_work_item_success_expectations(); // act @@ -1531,12 +1361,12 @@ TEST_FUNCTION(threadpool_create_work_item_succeeds_with_NULL_work_function_conte } -/* Tests_SRS_THREADPOOL_LINUX_05_006: [ If during the initialization of threadpool_work_item, malloc fails then threadpool_create_work_item shall fail. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_006: [ If during the initialization of threadpool_work_item, malloc fails then threadpool_create_work_item shall fail and return a NULL value. ]*/ TEST_FUNCTION(threadpool_create_work_item_fails_for_malloc) { // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; umock_c_negative_tests_snapshot(); @@ -1559,32 +1389,9 @@ TEST_FUNCTION(threadpool_create_work_item_fails_for_malloc) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_05_003: [ threadpool_create_work_item shall call sm_exec_begin. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_004: [ If sm_exec_begin returns SM_EXEC_REFUSED, threadpool_create_work_item shall fail and set the return variable threadpool_work_item a NULL value. ]*/ - -TEST_FUNCTION(threadpool_create_work_item_fails_when_threadpool_not_open) -{ - // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; - umock_c_reset_all_calls(); - - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); - - // act - threadpool_work_item = threadpool_create_work_item(threadpool, test_work_function, (void*)0x4243); - - // assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_IS_NULL(threadpool_work_item); - - // cleanup - THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); -} - /* threadpool_schedule_work_item */ -/* Tests_SRS_THREADPOOL_LINUX_05_010: [ If threadpool is NULL, threadpool_schedule_work_item shall fail and set the return variable with a non-zero value. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_010: [ If threadpool is NULL, threadpool_schedule_work_item shall fail and return a non-zero value. ]*/ TEST_FUNCTION(threadpool_schedule_work_item_with_NULL_threadpool_fails) { @@ -1599,14 +1406,13 @@ TEST_FUNCTION(threadpool_schedule_work_item_with_NULL_threadpool_fails) ASSERT_ARE_NOT_EQUAL(int, 0, work_item_schedule_result); } -/* Tests_SRS_THREADPOOL_LINUX_05_011: [ If threadpool_work_item is NULL, threadpool_schedule_work_item shall fail and set the return variable with a non-zero value. ] */ +/* Tests_SRS_THREADPOOL_LINUX_05_011: [ If threadpool_work_item is NULL, threadpool_schedule_work_item shall fail and return a non-zero value. ] */ TEST_FUNCTION(threadpool_schedule_work_item_with_NULL_work_function_fails) { // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - int work_item_schedule_result; - umock_c_reset_all_calls(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + int work_item_schedule_result; // act work_item_schedule_result = threadpool_schedule_work_item(threadpool, NULL); @@ -1619,50 +1425,21 @@ TEST_FUNCTION(threadpool_schedule_work_item_with_NULL_work_function_fails) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_05_012: [ threadpool_schedule_work_item shall call sm_exec_begin. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_013: [ If sm_exec_begin returns SM_EXEC_REFUSED, threadpool_schedule_work_item shall fail and set the return variable with a non-zero value. ]*/ - -TEST_FUNCTION(threadpool_schedule_work_item_fails_when_threadpool_not_open) -{ - // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - int result; - umock_c_reset_all_calls(); - - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); - - // act - result = threadpool_schedule_work_item(threadpool, (void*)0x4243); - - // assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - ASSERT_ARE_NOT_EQUAL(int, 0, result); - - // cleanup - THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); -} - -/* Tests_SRS_THREADPOOL_LINUX_05_012: [ threadpool_schedule_work_item shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_014: [ threadpool_schedule_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_015: [ threadpool_schedule_work_item shall increment the insert_pos. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_016: [ If task state is TASK_NOT_USED, threadpool_schedule_work_item shall set the current task state to TASK_INITIALIZING. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_017: [ threadpool_schedule_work_item shall release the shared SRW lock by calling srw_lock_release_shared ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_018: [ If the previous task state is not `TASK_NOT_USED` then threadpool_schedule_work_item shall increase task_array capacity ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_020: [ threadpool_schedule_work_item shall acquire the SRW lock in exclusive mode by calling srw_lock_acquire_exclusive. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_021: [ threadpool_schedule_work_item shall increment the pending_work_item_count and copy its address to pending_work_item_count_ptr into insert position in the task array. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_020: [ threadpool_schedule_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_exclusive. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_022: [ threadpool_schedule_work_item shall copy the work_function and work_function_context from threadpool_work_item into insert position in the task array. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_023: [ threadpool_schedule_work_item shall set the task_state to TASK_WAITING and then release the exclusive SRW lock by calling srw_lock_release_exclusive. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_024: [ threadpool_schedule_work_item shall notify a single thread that is waiting for update of this value by a wake signal. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_023: [ threadpool_schedule_work_item shall set the task_state to TASK_WAITING and then release the shared SRW lock by calling srw_lock_release_exclusive. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_025: [ threadpool_schedule_work_item shall unblock the threadpool semaphore by calling sem_post. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_026: [ threadpool_schedule_work_item shall set the return variable to 0 to indicate success. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_027: [ threadpool_schedule_work shall call sm_exec_end. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_028: [ threadpool_schedule_work_item shall return with the contents of the value of the return variable. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_026: [ threadpool_schedule_work_item shall succeed and return 0. ]*/ TEST_FUNCTION(threadpool_schedule_work_item_succeeds) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); - umock_c_reset_all_calls(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; threadpool_create_work_item_success_expectations(); @@ -1673,19 +1450,19 @@ TEST_FUNCTION(threadpool_schedule_work_item_succeeds) int result; - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_increment_64(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_compare_exchange(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_exclusive(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG)); - STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); - STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG)); + STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_acquire_exclusive(IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_release_exclusive(IGNORED_ARG)); STRICT_EXPECTED_CALL(mocked_sem_post(IGNORED_ARG)); - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + // act result = threadpool_schedule_work_item(threadpool, threadpool_work_item); @@ -1701,29 +1478,23 @@ TEST_FUNCTION(threadpool_schedule_work_item_succeeds) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_05_012: [ threadpool_schedule_work_item shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_014: [ threadpool_schedule_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_015: [ threadpool_schedule_work_item shall increment the insert_pos. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_016: [ If task state is TASK_NOT_USED, threadpool_schedule_work_item shall set the current task state to TASK_INITIALIZING. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_017: [ threadpool_schedule_work_item shall release the shared SRW lock by calling srw_lock_release_shared ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_018: [ If the previous task state is not `TASK_NOT_USED` then threadpool_schedule_work_item shall increase task_array capacity ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_019: [ If reallocating the task array fails, threadpool_schedule_work_item shall fail by setting the return variable a non-zero value and break. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_020: [ threadpool_schedule_work_item shall acquire the SRW lock in exclusive mode by calling srw_lock_acquire_exclusive. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_021: [ threadpool_schedule_work_item shall increment the pending_work_item_count and copy its address to pending_work_item_count_ptr into insert position in the task array. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_019: [ If reallocating the task array fails, threadpool_schedule_work_item shall fail and return a non-zero value. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_020: [ threadpool_schedule_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_exclusive. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_022: [ threadpool_schedule_work_item shall copy the work_function and work_function_context from threadpool_work_item into insert position in the task array. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_023: [ threadpool_schedule_work_item shall set the task_state to TASK_WAITING and then release the exclusive SRW lock by calling srw_lock_release_exclusive. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_024: [ threadpool_schedule_work_item shall notify a single thread that is waiting for update of this value by a wake signal. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_023: [ threadpool_schedule_work_item shall set the task_state to TASK_WAITING and then release the shared SRW lock by calling srw_lock_release_exclusive. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_025: [ threadpool_schedule_work_item shall unblock the threadpool semaphore by calling sem_post. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_026: [ threadpool_schedule_work_item shall set the return variable to 0 to indicate success. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_027: [ threadpool_schedule_work shall call sm_exec_end. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_028: [ threadpool_schedule_work_item shall return with the contents of the value of the return variable. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_026: [ threadpool_schedule_work_item shall succeed and return 0. ]*/ TEST_FUNCTION(threadpool_schedule_work_item_succeeds_realloc_array_with_no_empty_space) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); - umock_c_reset_all_calls(); - + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; threadpool_create_work_item_success_expectations(); threadpool_work_item = threadpool_create_work_item(threadpool, test_work_function, (void*)0x4243); @@ -1733,8 +1504,6 @@ TEST_FUNCTION(threadpool_schedule_work_item_succeeds_realloc_array_with_no_empty int result; - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_increment_64(IGNORED_ARG)); @@ -1758,13 +1527,12 @@ TEST_FUNCTION(threadpool_schedule_work_item_succeeds_realloc_array_with_no_empty STRICT_EXPECTED_CALL(interlocked_increment_64(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_compare_exchange(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_exclusive(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_increment(IGNORED_ARG)); - STRICT_EXPECTED_CALL(wake_by_address_single(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_release_shared(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_acquire_exclusive(IGNORED_ARG)); STRICT_EXPECTED_CALL(srw_lock_release_exclusive(IGNORED_ARG)); - STRICT_EXPECTED_CALL(mocked_sem_post(IGNORED_ARG)); - - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + STRICT_EXPECTED_CALL(mocked_sem_post(IGNORED_ARG)); // act result = threadpool_schedule_work_item(threadpool, threadpool_work_item); @@ -1781,22 +1549,18 @@ TEST_FUNCTION(threadpool_schedule_work_item_succeeds_realloc_array_with_no_empty THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_05_012: [ threadpool_schedule_work_item shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_014: [ threadpool_schedule_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_015: [ threadpool_schedule_work_item shall increment the insert_pos. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_016: [ If task state is TASK_NOT_USED, threadpool_schedule_work_item shall set the current task state to TASK_INITIALIZING. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_017: [ threadpool_schedule_work_item shall release the shared SRW lock by calling srw_lock_release_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_018: [ If the previous task state is not TASK_NOT_USED then threadpool_schedule_work_item shall increase task_array capacity. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_019: [ If reallocating the task array fails, threadpool_schedule_work_item shall fail by setting the return variable a non-zero value and break. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_027: [ threadpool_schedule_work_item shall call sm_exec_end. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_028: [ threadpool_schedule_work_item shall return with the contents of the value of the return variable. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_019: [ If reallocating the task array fails, threadpool_schedule_work_item shall fail and return a non-zero value. ]*/ TEST_FUNCTION(threadpool_schedule_work_item_fails_when_new_array_size_overflows) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); - umock_c_reset_all_calls(); - + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; threadpool_create_work_item_success_expectations(); threadpool_work_item = threadpool_create_work_item(threadpool, test_work_function, (void*)0x4243); @@ -1806,8 +1570,6 @@ TEST_FUNCTION(threadpool_schedule_work_item_fails_when_new_array_size_overflows) int result; - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_increment_64(IGNORED_ARG)); @@ -1816,9 +1578,7 @@ TEST_FUNCTION(threadpool_schedule_work_item_fails_when_new_array_size_overflows) STRICT_EXPECTED_CALL(srw_lock_acquire_exclusive(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)).SetReturn(INT32_MAX / 2 + 1); - STRICT_EXPECTED_CALL(srw_lock_release_exclusive(IGNORED_ARG)); - - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); + STRICT_EXPECTED_CALL(srw_lock_release_exclusive(IGNORED_ARG)); // act result = threadpool_schedule_work_item(threadpool, threadpool_work_item); @@ -1835,22 +1595,18 @@ TEST_FUNCTION(threadpool_schedule_work_item_fails_when_new_array_size_overflows) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_05_012: [ threadpool_schedule_work_item shall call sm_exec_begin. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_014: [ threadpool_schedule_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_015: [ threadpool_schedule_work_item shall increment the insert_pos. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_016: [ If task state is TASK_NOT_USED, threadpool_schedule_work_item shall set the current task state to TASK_INITIALIZING. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_017: [ threadpool_schedule_work_item shall release the shared SRW lock by calling srw_lock_release_shared. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_018: [ If the previous task state is not TASK_NOT_USED then threadpool_schedule_work_item shall increase task_array capacity. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_019: [ If reallocating the task array fails, threadpool_schedule_work_item shall fail by setting the return variable a non-zero value and break. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_027: [ threadpool_schedule_work_item shall call sm_exec_end. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_028: [ threadpool_schedule_work_item shall return with the contents of the value of the return variable. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_019: [ If reallocating the task array fails, threadpool_schedule_work_item shall fail and return a non-zero value. ]*/ TEST_FUNCTION(threadpool_schedule_work_item_fails_when_realloc_array_fails) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); - umock_c_reset_all_calls(); - + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; threadpool_create_work_item_success_expectations(); threadpool_work_item = threadpool_create_work_item(threadpool, test_work_function, (void*)0x4243); @@ -1860,8 +1616,6 @@ TEST_FUNCTION(threadpool_schedule_work_item_fails_when_realloc_array_fails) int result; - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); - STRICT_EXPECTED_CALL(srw_lock_acquire_shared(IGNORED_ARG)); STRICT_EXPECTED_CALL(interlocked_add(IGNORED_ARG, 0)); STRICT_EXPECTED_CALL(interlocked_increment_64(IGNORED_ARG)); @@ -1873,9 +1627,7 @@ TEST_FUNCTION(threadpool_schedule_work_item_fails_when_realloc_array_fails) STRICT_EXPECTED_CALL(interlocked_exchange(IGNORED_ARG, IGNORED_ARG)); STRICT_EXPECTED_CALL(realloc_2(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)).SetReturn(NULL); STRICT_EXPECTED_CALL(srw_lock_release_exclusive(IGNORED_ARG)); - - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); - + // act result = threadpool_schedule_work_item(threadpool, threadpool_work_item); @@ -1909,9 +1661,8 @@ TEST_FUNCTION(threadpool_destroy_work_item_with_NULL_threadpool_fails) TEST_FUNCTION(threadpool_destroy_work_item_with_NULL_threadpool_work_item_fails) { // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - umock_c_reset_all_calls(); - + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); + // call threadpool_destroy_work_item(threadpool, NULL); @@ -1922,34 +1673,13 @@ TEST_FUNCTION(threadpool_destroy_work_item_with_NULL_threadpool_work_item_fails) THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_05_031: [ threadpool_destroy_work_item shall call sm_exec_begin. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_032: [ If sm_exec_begin returns SM_EXEC_REFUSED, threadpool_destroy_work_item shall fail. ]*/ - -TEST_FUNCTION(threadpool_destroy_work_item_fails_when_threadpool_not_open) -{ - // arrange - THANDLE(THREADPOOL) threadpool = threadpool_create(test_execution_engine); - umock_c_reset_all_calls(); - // call - threadpool_destroy_work_item(threadpool, NULL); - - // assert - ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); - - // cleanup - THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); -} - -/* Tests_SRS_THREADPOOL_LINUX_05_031: [ threadpool_destroy_work_item shall call sm_exec_begin. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_033: [ Otherwise, threadpool_destroy_work_item shall wait for pending_work_item_count to become 0. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_033: [ threadpool_destroy_work_item shall wait for all pending work items to finish execution. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_037: [ If InterlockedHL_WaitForValue does not return INTERLOCKED_HL_OK then Log Message with severity CRITICAL and terminate. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_038: [ threadpool_destroy_work_item shall call sm_exec_end. ]*/ TEST_FUNCTION(threadpool_destroy_work_item_fails_for_InterlockedHL_WaitForValue_returns_INTERLOCKED_HL_ERROR) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); - umock_c_reset_all_calls(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; threadpool_create_work_item_success_expectations(); @@ -1958,11 +1688,9 @@ TEST_FUNCTION(threadpool_destroy_work_item_fails_for_InterlockedHL_WaitForValue_ ASSERT_IS_NOT_NULL(threadpool_work_item); umock_c_reset_all_calls(); - STRICT_EXPECTED_CALL(sm_exec_begin(IGNORED_ARG)); STRICT_EXPECTED_CALL(InterlockedHL_WaitForValue(IGNORED_ARG, IGNORED_ARG, IGNORED_ARG)).SetReturn(INTERLOCKED_HL_ERROR); STRICT_EXPECTED_CALL(ps_util_terminate_process()); - STRICT_EXPECTED_CALL(sm_exec_end(IGNORED_ARG)); - + threadpool_destroy_work_item(threadpool, threadpool_work_item); // assert @@ -1976,18 +1704,12 @@ TEST_FUNCTION(threadpool_destroy_work_item_fails_for_InterlockedHL_WaitForValue_ THANDLE_ASSIGN(THREADPOOL)(&threadpool, NULL); } -/* Tests_SRS_THREADPOOL_LINUX_05_031: [ threadpool_destroy_work_item shall call sm_exec_begin. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_033: [ Otherwise, threadpool_destroy_work_item shall wait for pending_work_item_count to become 0. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_034: [ When pending_work_item_count becomes 0, threadpool_destroy_work_item shall acquire the SRW lock in shared mode by calling srw_lock_acquire_shared. ]*/ +/* Tests_SRS_THREADPOOL_LINUX_05_033: [ threadpool_destroy_work_item shall wait for all pending work items to finish execution. ]*/ /* Tests_SRS_THREADPOOL_LINUX_05_035: [ threadpool_destroy_work_item shall free the memory allocated to the work item of type THREADPOOL_WORK_ITEM_HANDLE created in threadpool_create_work_item. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_036: [ threadpool_destroy_work_item shall release the shared SRW lock. ]*/ -/* Tests_SRS_THREADPOOL_LINUX_05_038: [ threadpool_destroy_work_item shall call sm_exec_end. ]*/ - TEST_FUNCTION(threadpool_destroy_work_item_succeeds) { // arrange - THANDLE(THREADPOOL) threadpool = test_create_and_open_threadpool(); - umock_c_reset_all_calls(); + THANDLE(THREADPOOL) threadpool = test_create_threadpool(); THREADPOOL_WORK_ITEM_HANDLE threadpool_work_item; threadpool_create_work_item_success_expectations();