1

I have implemented sort of user level threads system.I need some help with implementation of a counting semaphore, using binary semaphore implementation(up and down functions as described below). Here is the interface of my implementation of a binary semaphore:

typedef enum BinSemStatus{
   locked,
   unlocked
} BinSemStatus;


struct semaphore {
BinSemStatus status;
int bid;
};

int bsem_alloc();//allocate a new binary semaphore,return its descriptor
void bsem_free(int id);
void bsem_down(int id);
void bsem_up(int id);

And here is the interface of the counting semaphore interface:

struct counting_semaphore* counting_alloc(uint value);
counting_free(struct counting_semaphore* sem);

// If the value representing the count of
// the semaphore variable is not negative, decrement it by 1. If the 
// semaphore variable is now
// negative, the thread executing acquire is blocked until the value is 
// greater or equal to 1.
// Otherwise, the thread continues execution.
void up(struct counting_semaphore* sem);
// Increments the value of semaphore
// variable by 1.
void down(struct counting_semaphore* sem);

What I have tried to do is at void up(struct counting_semaphore* sem) to lock value.But as you can see below that is not enough.I have added a comment at the problematic case.

struct counting_semaphore {
int binary_descriptor;
int value;
}; 

void down(struct counting_semaphore *sem){
  bsem_down(sem->binary_descriptor);
  if (sem->value > 0){
    sem->value--;
  }
  else{
     //not sure what to do here, maybe use anather semaphore in some way?
  } 
  bsem_up(sem->binary_descriptor);
 }
void up(struct counting_semaphore *sem){
  bsem_down(sem->binary_descriptor);
  sem->value++;
  bsem_up(sem->binary_descriptor);
}
David
  • 733
  • 2
  • 11
  • 30

2 Answers2

0

When sem->value reaches 0, the thread blocks, and it is time to reschedule. You didn't show your scheduling code, so I cannot give a concrete advice. Possibly a scheduler should call bsem_up(sem->binary_descriptor); on behalf of the thread.

user58697
  • 7,808
  • 1
  • 14
  • 28
0

The critical section is guarded by sem->binary_descriptor1 and each of the operations down(S) and up(S) uses it to correctly update the value of sem.value

After updating both operations release the sem->binary_descriptor2 semaphore only if the value is positive.

S.value is never negative because any process performing down(S) is blocked at sem->binary_descriptor2.

  struct counting_semaphore* counting_semaphore_alloc(int value) {

    struct counting_semaphore* sem = malloc(sizeof(struct counting_semaphore));
    sem->value = value;
    sem->binary_descriptor1= bsem_alloc();//locks the value
    sem->binary_descriptor2= bsem_alloc();//locks the sing of the value
    if (value <= 0) {
        bsem_down(sem->binary_descriptor2);
    }
    return sem;
    }

void down(struct counting_semaphore *sem){
    bsem_down(sem->binary_descriptor2);
    bsem_down(sem->binary_descriptor1);
    sem->value--;
    if (sem->value>0){
        bsem_up(sem->binary_descriptor2);
    }
    bsem_up(sem->binary_descriptor1);
}


void up(struct counting_semaphore* sem) {
    bsem_down(sem->binary_descriptor1);
    sem->value++;
    if (sem->value == 1) {
        bsem_up(sem->binary_descriptor2);
    }
    bsem_up(sem->binary_descriptor1);
}
David
  • 733
  • 2
  • 11
  • 30