From Kerrighed

Contents

[edit] IPC Semaphore

[edit] Handling sem_undo double lists

[edit] Linux implementation

struct sem_undo {
        struct sem_undo *       proc_next;      /* next entry on this process */
        struct sem_undo *       id_next;        /* next entry on this semaphore set */
        int                     semid;          /* semaphore set identifier */
        short *                 semadj;         /* array of adjustments, one per semaphore */
};

In current Linux implementation (2.6.20), the semundo is in two lists :

  • a list per semaphore: id_next
  • a list per process: proc_next. (This list is in reality shared by processes created with CLONE_SYSVSEM on fork)

[edit] Kerrighed implementation

struct sem_undo {
        unique_id_t             proc_list_id;   /* proc_list identifier */
        struct sem_undo *       id_next;        /* next entry on this semaphore set */
        int                     semid;          /* semaphore set identifier */
        short *                 semadj;         /* array of adjustments, one per semaphore */
        int                     nsems;          /* no. of semaphores in array */
};
 
 
/* structures used by semundolst_io_linker */
 
struct semundo_id {
	int semid;
	struct semundo_id * next;
};
 
typedef struct semundo_list_object {
	atomic_t refcnt;
	atomic_t semcnt;
	struct semundo_id * list;
} semundo_list_object_t;

The proc_next value is replaced by identifier proc_list_id of the undo list owned by processes. A list of semid per proc_list_id is stored in a kddm object: semundo_list_object.

The following lines describe some implentation algorithms in pseudo-code for functions using the undo list per semaphore or the undo list per process.

  1. freeary()
for each sem_undo ''undo'' in semaphore undo list:
	semundo_list_object_t undoid = kddm_grab(undo->proc_list_id);
	for each semundo_id ''un'' in undoid->list:
		if (un->semid == undo->semid)
			remove un
			break
	remove undo
end
  1. find_undo()
unique_id_t undo_list_id = current->sysvsem.undolist_id;
for each sem_undo in semaphore undo list:
	if (undo->listid == undo_list_id)
		return undo

create a new <tt>sem_undo</tt> ''un''
add ''un'' in the semaphore undo list
add semid in the semundo_object with id undo_list_id
return ''un''
  1. semctl(SET_ALL)
for each sem_undo in the semaphore undo list:
	reset the semadj
  1. exit_sem()
unique_id_t undo_list_id = current->sysvsem.undolist_id;
semundo_list_object = kddm_grab(undo_list_id)

for each semid in semundo_list_object:
	sma = semlock(semid)
	for each sem_undo in semaphore undo list:
		if (undo->listid == undo_list_id)
			remove undo
	semunlock(sma)

kddm_put(undo_list_id)

[edit] Contributions

This page has been initiated by :