Реализация счетного семафора с использованием двоичного семафора
Я реализовал своего рода систему потоков пользовательского уровня. Мне нужна помощь с реализацией счетного семафора, использующего реализацию двоичного семафора (функции вверх и вниз, как описано ниже). Вот интерфейс моей реализации двоичного семафора:
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);
А вот интерфейс интерфейса подсчета семафоров:
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);
То, что я пытался сделать, это void up(struct counting_semaphore* sem), чтобы заблокировать значение. Но, как вы можете видеть ниже, этого недостаточно. Я добавил комментарий к проблемному случаю.
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);
}
2 ответа
Критическая секция защищена sem->binary_descriptor1, и каждая из операций down(S) и up(S) использует ее для корректного обновления значения sem.value. После обновления обеих операций освободите семафор sem->binary_descriptor2, только если значение равно положительный S.value никогда не бывает отрицательным, потому что любой процесс, выполняющий down(S), блокируется в 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);
}
Когда sem->value
достигает 0, поток блокируется, и пришло время перепланировать. Вы не показывали свой код планирования, поэтому я не могу дать конкретный совет. Возможно, планировщик должен вызвать bsem_up(sem->binary_descriptor);
от имени потока.