
CONFIG_HZ = 250)
jiffies는 jiffies_64 시작 주소를 기준으로 4byte 주소 공간에 있는 값을 저장jiffies_64는 8byte 단위로 주소 공간에 있는 값을 저장

Migration)rpi_set_synchronize()함수를 실행하는 도중 인터럽트가 발생해 다시 rpi_set_synchronize()함수에 진입함선점 스케줄링 : CPU 코어에서 실행중인 프로세스를 강제로 실행을 멈추게 하고 우선순위가 높은 프로세스를 강제로 실행하게 함
대부분의 리눅스 커널은 Preemptive Scheduling 환경에서 실행
우리가 입력한 코드 블록이 실행되는 도중 Preemptive Scheduling 될 수 있음
struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), void *data, int node,
const char namefmt[], va_list args)
{
DECLARE_COMPLETION_ONSTACK(done);
struct task_struct *task;
struct kthread_create_info *create = kmalloc(sizeof(*create),
GFP_KERNEL);
spin_lock(&kthread_create_lock); // 스핀락을 획득
list_add_tail(&create->list, &kthread_create_list); // Critical Section
spin_unlock(&kthread_create_lock); // 스핀락을 해제
wake_up_process(kthreadd_task);
}
busy_waiting : A 프로세스가 spin lock 획득한 다음 idr_find()를 실행하고 있는데
다른 프로세스가 spin lock을 획득하려 하면 이 spin lock이 해제돼서 자신이 spin lock을 할 수 있을 때 까지 기다림
static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
{
struct glink_channel *channel;
spin_lock(&glink->idr_lock); // 스핀락을 획득
channel = idr_find(&glink->lcids, lcid); // Critical Section
spin_unlock(&glink->idr_lock); // 스핀락을 해제
if (!channel) {
dev_err(glink->dev, "Invalid open ack packet\n");
return -EINVAL;
}
complete_all(&channel->open_ack);
return 0;
}
같은 mutex_lock를 2번 사용하면 큰일 남!
mutex_lock을 걸고 또 걸면 자신이 mutex_lock을 건 상태에서 다시 걸면 sleep에 진입하면서 자신을 깨워주길 기다려야 하므로 영원히 깨어나지 못함
sleep을 지원하며 프로세스 컨텍스트에서 주로 쓰는 커널 동기화 기법
static void dbs_work_handler(struct work_struct *work)
{
struct policy_dbs_info *policy_dbs;
struct cpufreq_policy *policy;
struct dbs_governor *gov;
policy_dbs = container_of(work, struct policy_dbs_info, work);
policy = policy_dbs->policy;
gov = dbs_governor_of(policy);
/*
* Make sure cpufreq_governor_limits() isn't evaluating load or the
* ondemand governor isn't updating the sampling rate in parallel.
*/
mutex_lock(&policy_dbs->update_mutex);
gov_update_sample_delay(policy_dbs, gov->gov_dbs_update(policy));
mutex_unlock(&policy_dbs->update_mutex);
...
}
mutex_lock(&group->mutex);
iommu_alloc_default_domain(group,dev);
mutex_unlock(&group->mutex);
if(group->default.domain){
ret = _iommu_attach_device(group->default_domain, dev);
static void qaic_postclose(struct drm_device *dev, struct drm_file *file)
{
mutex_lock(&qddev->users_mutex);
if(!list_empty(&usr->node))
list_del_init(&usr->node);
mutex_unlock(&qddev->users_mutex);
owner : 해당 뮤텍스가 해제가 되었는지 lock 되었는지 확인할 수 있는 필드
wait_list : 뮤텍스가 한번도 획득되지 않았다면 wait_list가 비워져있음
다른 프로세스가 뮤텍스 획득을 시도하면 자신을 wait_list에 등록함
struct mutex {
atomic_long t owner; // 뮤텍스를 획득한 프로세스의 task descriptor 주소
raw_spinlock_t wait_lock;
#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
struct optimistic_spin_queue osq; /* Spinner MCS lock */
#endif
struct list_head wait_list; // 뮤텍스를 기다리는 프로세스의 정보
#ifdef CONFIG_DEBUG_MUTEXES
void *magic;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_mapdep_map;
#endif
};