현재 상황 : lock, semaphore, conditional variable → FIFO

/* A counting semaphore. */
struct semaphore {
	unsigned value;             /* Current value. */
	struct list waiters;        /* List of waiting threads. */
};

/* Lock. */
struct lock {
	struct thread *holder;      /* Thread holding lock (for debugging). */
	struct semaphore semaphore; /* Binary semaphore controlling access. */
};

/* Condition variable. */
struct condition {
	struct list waiters;        /* List of waiting threads. */
};

lock

/* Lock. */
struct lock {
	struct thread *holder;      /* Thread holding lock (for debugging). */
	struct semaphore semaphore; /* Binary semaphore controlling access. */
};

synch.c/lock_init()

/* Initializes LOCK.  A lock can be held by at most a single
   thread at any given time.  Our locks are not "recursive", that
   is, it is an error for the thread currently holding a lock to
   try to acquire that lock.

   A lock is a specialization of a semaphore with an initial
   value of 1.  The difference between a lock and such a
   semaphore is twofold.  First, a semaphore can have a value
   greater than 1, but a lock can only be owned by a single
   thread at a time.  Second, a semaphore does not have an owner,
   meaning that one thread can "down" the semaphore and then
   another one "up" it, but with a lock the same thread must both
   acquire and release it.  When these restrictions prove
   onerous, it's a good sign that a semaphore should be used,
   instead of a lock. */
void
lock_init (struct lock *lock) {
	ASSERT (lock != NULL);

	lock->holder = NULL;
	sema_init (&lock->semaphore, 1);
}

synch.c/lock_acquire()

무조건 현재 락을 소유하고 있지 않은 스레드만 가능하다.

해당 공유자원을 활용할 때 쓴다. 현재 공유자원을 사용하기 위해 lock의 value(sema)를 0으로 낮춰주고 그 다음 코드로 진행한다.

만약 현재 value(sema)가 0이라면 이미 누군가가 공유 자원을 사용 중이라는 의미이므로 while문을 돌면서 waiting list에서 대기하게 된다.

/* Acquires LOCK, sleeping until it becomes available if
   necessary.  The lock must not already be held by the current
   thread.

   This function may sleep, so it must not be called within an
   interrupt handler.  This function may be called with
   interrupts disabled, but interrupts will be turned back on if
   we need to sleep. */
void
lock_acquire (struct lock *lock) {
	ASSERT (lock != NULL);
	ASSERT (!intr_context ());
	ASSERT (!lock_held_by_current_thread (lock));   // 무조건 락을 소유하고 있지 않은 스레드만 가능

	sema_down (&lock->semaphore);   // 만약 
	lock->holder = thread_current ();  // 현재 lock의 권한을 갖고 있는 스레드를 명시해준다.
}

synch.c/lock_release()