程序代写CS代考 data structure concurrency SOFT3410 Tutorial 7 Atomics and Unit Testing – cscodehelp代写

SOFT3410 Tutorial 7 Atomics and Unit Testing
Question 1: Atomic Operations, Counting and Stacks
As we have noted prior, race conditions occur when we have more than one thread mutating shared memory. Atomics actually allow us to deal with this situation by making the write visible to other threads, this occurs in a single operation on the hardware itself.
Simply start by writing a program where multiple threads will increment the shared counter.
atomic_int counter = 0; void increment() {
}
atomic_fetch_add(&counter, 1);
• Set up your threads and a worker function to continually increment the counter, observe the result at the end of execution
• What do you observe with this code?
• Doyouobservesignificantperformancedifferencesbetweensinglethreadedandmulti-threaded performance?
1

Question 2: Atomic Stack
Construct a linked stack data structure which is where the last node pushed would be the first node to be popped. Try and make your stack a generic stack that can be associated with any data type.
struct stack_node; struct stack;
/**
* @return stack, returns a new stack object on the heap
*/
struct stack* stack_new(); /**
* Pushes a new object on the stack, this will be at the
* top of the stack.
* @param stack
* @param data
*/
void stack_push(struct stack*, void* data); /**
* Pops the last element from the top of the stack.
* @param stack
* @return object, object at the top of the stack
*/
void* stack_pop(struct stack*); /**
* Destroys the stack, deallocates any memory associated with it.
* @param stack
*/
void stack_destroy(struct stack*);
Once you have constructed stack, consider how you can apply atomic operations to the stack? How
could you make your stack usable from multiple threads without using locks.
• You will need to use a atomic_compare_exchange_* function for this task • What should you do if the operation fails?
• Discuss how you would implement the push and pop operation of your program
SOFT3410 Atomics and Unit Testing
Concurrency Page 2 of 4

};
SOFT3410 Atomics and Unit Testing
Question 3: Cmocka
Once you have constructed both your atomic stack and counter, use CMocka to test your application. You can use the following template and documentation to get started.
#include
#include
#include
#include
#include
static void test_equals_five(void** state) { int i = 5;
assert_int_equal(i, 5);
}
int main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_equals_five), return cmocka_run_group_tests(tests, NULL, NULL);
}
Question 4: Test and Set Lock
Using what you have learned from atomic operations and write your own lock mechanism. Use the following scaffold to start building your test and set spinlock.
struct tas; /**
* @pram taslock, initialises the handle for the taslock
*/
void tas_init(struct tas*); /**
* Locks, operation should be successful if the lock is valid.
* If the lock is invalid, the lock operation returns a non-zero integer
* tas lock that is currently in a locked state will keep threads waiting.
* @param taslock
* @return success
*/
int tas_lock(struct tas* t);
Concurrency Page 3 of 4

/**
* Unlocks, operation should be successful is the lock is valid.
* If the lock is invalid, unlock operation returns a non-zero integer.
* @param taslock
* @return success
*/
int tas_unlock(struct tas* t); /**
* Destroys the tas lock, puts it in an invalid state
* @param taslock
*/
void tas_destroy(struct tas* t);
If the test and set lock has been initialised, the lock and unlock functions should return the value 0 to
indicate a success. Non-zero is reserved for errors regarding the lock.
• Construct your test and set spinlock
• Construct a test suite to ensure that it can handle multiple threads and applied to normal lock object
Question 5: Busy-Waiting Semaphore
Using your test and set lock as a base, make a few modifications to implement a counting semaphore.
Question 6: Busy-Waiting Barrier
Synchronisation primitives are all the rage these days and in this task, you will need to construct a barrier. Use the following struct to help guide your implementation. This synchronisation primitive will keep threads waiting until all threads have arrived at the barrier. Once ready, they will be released to continue with their execution.
struct sync_barrier { uint16_t threshold;
atomic_uint counter; atomic_uint release_count;
};
struct sync_barrier* sync_barrier_new();
int sync_barrier* sync_barrier_wait(struct sync_barrier*); void sync_barrier_destroy(struct sync_barrier*);
SOFT3410 Atomics and Unit Testing
Concurrency
Page 4 of 4

Leave a Reply

Your email address will not be published. Required fields are marked *