M.E. Lоck The cоntext fоr this question is the sаme аs the previous question. You hаve designed a bus-based custom non-cache-coherent shared memory DSP (Digital Signal Processor). Each CPU in the DSP has a private cache. The hardware provides the following primitives for the interaction between the private cache of a CPU and the shared memory: fetch(addr): Pulls the latest value from main memory into the cache flush(addr): Pushes the value at addr in the cache to main memory; it does not evict it from the cache hold(addr): Locks the memory bus for addr; no other core can fetch or flush this address until released unhold(addr): Releases the lock on addr You got this generic implementation for a ticket lock algorithm and tried it on your architecture. It did not work. struct ticket_lock { int next_ticket; // The next ticket number to give out int now_serving; // The ticket number currently allowed to enter}; void lock(struct ticket_lock *l) { // Acquire ticket int my_ticket = l->next_ticket++; // Wait for turn while (l->now_serving != my_ticket) { // Spin }} void unlock(struct ticket_lock *l) { l->now_serving++; // Release} c) [4 points] We have provided a skeleton of the fixed lock() and unlock() functions below. Fill in the numbered blanks (1 through 4) and write your answer with the correct primitive (fetch, flush, hold, or unhold) to make the ticket lock function correctly on your non-cache-coherent DSP. void lock(struct ticket_lock *l) { // Acquire ticket atomically ___1___(&l->next_ticket); fetch(&l->next_ticket); int my_ticket = l->next_ticket++; ___2___(&l->next_ticket); unhold(&l->next_ticket); // Wait for turn fetch(&l->now_serving); while (l->now_serving != my_ticket) { ____3___(&l->now_serving); }} void unlock(struct ticket_lock *l) { // Release l->now_serving++; ___4___(&l->now_serving); }