Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

For an OS class, I currently have to create a thread-safe queue in the linux kernel that one interacts with using syscalls.

Now for the critical sections my gut feeling is that I would want to use the mutex_lock and mutex_unlock functions in the mutex.h header. However, I was told that I could instead use a binary semaphore with down_interruptible and up in the semaphore.h header, and that it'd be better.

I've read through Difference between binary semaphore and mutex: From it, I understand that the main advantage of a mutex is how strongly it enforces ownership, and that the advantage of the semaphore is that since it doesn't enforce ownership you can use it as a synchronization mechanism between two (multiple?) different threads.

My question is what are the advantages of the binary semaphore, if you use it in exactly the same way as a mutex. More explicitly if I wrote:

down()
/* critical */
up()

in the same way that I would do

mutex_lock()
/* critical */
mutex_unlock()

Is there some performance advantage because it's less safe than a mutex? Am I missing something?


Here's a small snippet of the code that I want to make thread-safe if you want more context (this is my first C proj ever):

#define MESSAGE_MAX_SIZE 512

typedef struct list_head list_node;

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

/* 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) {
  long res = 0;
  Message *msg = 0; 

  if (len < 0) return EINVAL;
  if (len > MESSAGE_MAX_SIZE) return E2BIG;

  msg = kmalloc(sizeof(Message), GFP_KERNEL);
  if (msg == 0) return ENOMEM;

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

  /* Start Critical Section */

  my_q.size++;
  list_add_tail(&msg->node, &my_q.head);

  /* End Critical Section   */

  return 0;
}
like image 389
m0meni Avatar asked Oct 27 '16 18:10

m0meni


People also ask

Which is better binary semaphore or mutex?

If you have number of instances for resource it is better to use Binary semaphore. If you have single instance for resource it is better to use mutex.

What is the advantage of semaphore over mutex?

A mutex object allows multiple process threads to access a single shared resource but only one at a time. On the other hand, semaphore allows multiple process threads to access the finite instance of the resource until available.

Can semaphores be used for mutual exclusion?

Semaphores serve another important purpose, mutual exclusion. Two or more processes engage in mutual exclusion when they cooperate so that only one of them ob- tains access to a shared resource at a given time. For example, suppose two executing processes each need to insert items into a shared linked list.

What is a mutex how it is different from a binary semaphore?

Main difference between Mutex and Binary semaphore is in Mutext if thread lock the critical section then it has to unlock critical section no other thread can unlock it, but in case of Binary semaphore if one thread locks critical section using wait(s) function then value of s become "0" and no one can access it until ...


1 Answers

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.

like image 78
bytefire Avatar answered Oct 23 '22 11:10

bytefire