Are there any advantages to using a binary semaphore instead of a mutex for mutual exclusion in a critical section of a queue? Are there any advantages to using a binary semaphore instead of a mutex for mutual exclusion in a critical section of a queue? multithreading multithreading

Are there any advantages to using a binary semaphore instead of a mutex for mutual exclusion in a critical section of a queue?


In absence of empirical evidence, I'd quote from the book Linux Kernel Development

It (i.e. mutex) behaves similar to a semaphore with a count of one, but it has a simpler interface, more efficient performance, and additional constraints on its use.

Additionally, there are many constraints that apply to mutexes but not to semaphores. Things like process cannot exit while holding a mutex. Moreover, if CONFIG_DEBUG_MUTEXES kernel option is enabled, then all the constraints that apply on mutexes are ensured by debugging checks.

So, unless there is a good reason not to use mutex, that should be first choice.


The default locking primitive is the spinlock. Mutexes only make sense if you need to sleep while holding the lock, which you definitely don't in the aforementioned code sample.

#define MESSAGE_MAX_SIZE 512typedef struct list_head list_node;

Why?

/* Create message struct */typedef struct {  size_t size;  list_node node;  char data[MESSAGE_MAX_SIZE];} Message;

Weird order, the node pointer should either be first or last.

/* Create the linked list queue with dummy head */struct {  size_t size;  list_node head;} my_q = { 0, LIST_HEAD_INIT(my_q.head) };/*  Adds a new item to the tail of the queue.   @data: pointer to data to add to list  @len: size of the data*/asmlinkage long sys_enqueue(const void __user *data, long len) {

The curly bracket should be on the next line. Why is the length of signed type?

  long res = 0;  Message *msg = 0; 

Why are you initializing these her and why are you setting the pointer to 0 as opposed to NULL?

  if (len < 0) return EINVAL;

The return statement should be on the next line. Also note this condition would not be relevant if the type was unsigned to begin with.

  if (len > MESSAGE_MAX_SIZE) return E2BIG;  msg = kmalloc(sizeof(Message), GFP_KERNEL);

Why not sizeof(*msg)

  if (msg == 0) return ENOMEM;  res = copy_from_user(msg->data, data, len);  if (res != 0) return EFAULT;

This leaks msg.

  /* Start Critical Section */  my_q.size++;  list_add_tail(&msg->node, &my_q.head);  /* End Critical Section   */  return 0;}