LINUX.ORG.RU

Почему для синхронизации do_settimeofday with do_gettimeofday исользуются rw-блокировки(спинлоки) а не семафоры?


0

0

я попытался засинхронизировать сисколы семафорами но пользующие сисколы процессы систематически зависают на СВОБОДНЫХ семафорах/мьютексах

★★★★★
Ответ на: комментарий от Spectrum

ну есть в ядре некий мютекс DECLARE_MUTEX(mut1);

и есть два сискола

int my_syscall_1(...){
down(&m1);
//do something
up(&m1)
}

и

int my_syscall_2(...){
down(&m1);
//do something
up(&m1)
}

если я поочереди вызываю оба сискола из одного процесса то второй сискол подвисает на down(&m1);

в чём может быть трабл не знаю но меня смутили спинлоки в стандартных сисколах

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

ну сколько уж можно повторять ...
MAN LDD 3 !!!

p.134

Spinlocks

Semaphores are a useful tool for mutual exclusion, but they are not the only such
tool provided by the kernel. Instead, most locking is implemented with a mechanism
called a spinlock. __Unlike semaphores__, spinlocks may be used in code __that cannot
sleep__, such as interrupt handlers. When properly used, __spinlocks offer higher
performance than semaphores in general__. They do, however, bring a different set of
constraints on their use.

Чукча не читатель, чукча писатель ...

RomanU
()
Ответ на: комментарий от RomanU

ну хватит юморить.

случай с обработчиками прерываний это отдельная песня. у меня с ними ничего синхронизировать не требуется.

быстродействие тоже вопрос второстепенный

а вот почему не работают семафоры...? в конкретной ситуации случайно нет противопоказаний к их использованию? ядро 2.4.18

а насколько изменились реализации семафоров с 2.4 до 2.6?

>MAN LDD 3 !!!

в предисловии написано что для ядер 2.4 рекомендуется читать ldd2

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

Я думаю, что ответ всё же заключается в строчке:
"Unlike semaphores, spinlocks may be used in code that cannot
sleep"

Если ты не думаешь засыпать, в твоём сисколе нужно использовать спинлок.
И поэтому do_gettimeofday и подобные используют спинлоки.
Имхо.

RomanU
()
Ответ на: комментарий от RomanU

>Я думаю, что ответ всё же заключается в строчке: >"Unlike semaphores, spinlocks may be used in code that cannot sleep"

если сисколы относятся к коду который не может спать то вы правы, но прямых указаний на это я не помню

>И поэтому do_gettimeofday и подобные используют спинлоки.

do_gettimeofday использует спинлоки ибо лочат ресурс используемый в обработчике прерывания.

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

>>И поэтому do_gettimeofday и подобные используют спинлоки.

>do_gettimeofday использует спинлоки ибо лочат ресурс используемый в обработчике прерывания.

но может ещё какието есть причины но я больше не знаю

cvv ★★★★★
() автор топика
Ответ на: комментарий от Spectr

а хоть какойто аргумент в пользу такого решения??

cvv ★★★★★
() автор топика
Ответ на: комментарий от Spectr

> первое, что приходит на ум, это все же лучше использовать down_interruptible, вместо down ...

down_interruptible - это для того, чтобы зависший юзерский процесс можно было кильнуть. В случае down этого сделать будет нельзя, пока процесс не получит своё.

Так что это тут не совсем по теме будет.

RomanU
()
Ответ на: комментарий от RomanU

> В случае down этого сделать будет нельзя, пока процесс не получит своё.

А если процесс "слетит", или будет неубиваемым (у меня было такое после down) - то тогда усе, reboot... Ибо мютекс будет залоченным.

К автору поста - а ты уверен, что у тебя нет места, где up "перепрыгивается" ? Тогда - меняй ядро, компилятор (про компилятор вообще говорят, что ядро стоит собирать только с рекомендуемым gcc - с другим и не гарантируется, что все будет ок) - вобщем, с бубном тогда прыгать...

Spectr ★★★
()
Ответ на: комментарий от Spectr

>К автору поста - а ты уверен, что у тебя нет места, где up "перепрыгивается" ? 
та какбудто нет. завтра сырцы покажу

>Тогда - меняй ядро, 
нельзя по ТЗ. ядро не самособранное, в моём случае ASP

>компилятор (про компилятор вообще говорят, что ядро стоит собирать только с рекомендуемым gcc - с другим и не гарантируется, что все будет ок)
ASP как-будто собирала тем-же компилером что и я

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

фрагменты исходников


typedef struct{
    int fd;
    send_buf_id_t sendbuf_id;
    struct rw_semaphore mutex;
}fd_set_item_t;


//создаём и инициализируем новый массив
static fd_set_item_t*fd_set_arr_new(void){
    unsigned i;
    fd_set_item_t*fd_set_arr;
    if(!(fd_set_arr   =   kmalloc(sizeof(fd_set_item_t)*__FD_SETSIZE, GFP_USER))){
        printk("Out of memory");//ругаемся  
        //@todo:хорошо подумать что делаем в случае отсутствия свободной памяти 
        return NULL;
    }
    for (i=0; i<__FD_SETSIZE; i++){
        fd_set_arr[i].sendbuf_id=0LL;
        init_rwsem(&fd_set_arr[i].mutex);
    }
    return fd_set_arr;
}


код на котором собственно происходит подвисание:
    fd_set_item_t*fd_set_arr=fd_set_arr_new();


    for(j=0; j<__FD_SETSIZE; j++){
        printk(__func__":%ld:j=%u\n",(long)current->pid,j);
        down(&send_buf_arr[j].mutex);//ЗАВИСАЕТ ЗДЕСЬ при j=0
        if(send_buf_arr[j].id==sendbuf_id){ sendbuf=&send_buf_arr[j]; j=__FD_SETSIZE; }
        up(&send_buf_arr[j].mutex);
    }
 

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

что зависает - это не удивительно.

удивительно то, что это компилируется.

> struct rw_semaphore mutex
> ...
> down(&send_buf_arr[j].mutex)

должно быть down_read или down_write

idle ★★★★★
()
Ответ на: комментарий от idle

>что зависает - это не удивительно.

>удивительно то, что это компилируется.

извиняюсь не тот код дал

typedef struct{
    struct semaphore mutex;//@todo:mutex, возможно имеет смысл юзать rwsem 
    proto_t       proto[PROTO_QTY];
    protocol_t    protocol;
    perm_t        allow;
    unsigned int  size;
    unsigned char buf[HTTP_LINE_MAX_SIZE];
    send_buf_id_t id;
    unsigned      use_counter;
}send_buf_t;


send_buf_t        send_buf_arr[__FD_SETSIZE]={};

//инициализация
    for (i=0;i<__FD_SETSIZE;i++){
        init_MUTEX(&send_buf_arr[i].mutex);
        send_buf_arr[i].id =0LL;
        send_buf_arr[i].size=0;
        send_buf_arr[i].allow=SBP_UNDEFINED;
        send_buf_arr[i].use_counter=0;
        memset(&send_buf_arr[i].protocol,0,sizeof(protocol_t));
        send_buf_arr[i].protocol.proto=PROTO_UNDEFINED;
        for(j=0;  j<PROTO_QTY;  j++)send_buf_arr[i].proto[j]=PROTO_UNDEFINED;
    }


код на котором собственно происходит подвисание:


  for(j=0; j<__FD_SETSIZE; j++){
        printk(__func__":%ld:j=%u try lock send_buf_arr[j].mutex\n",(long)current->pid,j);
        down(&send_buf_arr[j].mutex);//ЗАВИСАЕТ ЗДЕСЬ
        if(send_buf_arr[j].id==sendbuf_id){ sendbuf=&send_buf_arr[j]; j=__FD_SETSIZE; }
        up(&send_buf_arr[j].mutex);
        printk(__func__":%ld:j=%u send_buf_arr[j].mutex unlocked\n",(long)current->pid,j);
    }

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

код-то, конечно, неправильный ...

> if(send_buf_arr[j].id==sendbuf_id){ sendbuf=&send_buf_arr[j]; j=__FD_SETSIZE; }

j=__FD_SETSIZE - это, я полагаю, чтобы цикл завершился

> up(&send_buf_arr[j].mutex);

и какому же семафору вы говорите "up" ?

правильно, его и нету вовсе, выход за границы массива

idle ★★★★★
()
Ответ на: комментарий от cvv

>ещё раз спасибо, всё работает

извиняюсь, работает не всё, но код в котором вы нашли ошибку работает

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

ещё код, на мой взгляд более прямой но всёравно не работает

ypedef struct{
    int fd;
    send_buf_id_t sendbuf_id;
    struct rw_semaphore mutex;
}fd_set_item_t;


//создаём и инициализируем новый массив
static fd_set_item_t*fd_set_arr_new(void){
    unsigned i;
    fd_set_item_t*fd_set_arr;
    if(!(fd_set_arr   =   kmalloc(sizeof(fd_set_item_t)*__FD_SETSIZE, GFP_USER))){
        printk("Out of memory");//ругаемся  
        //@todo:хорошо подумать что делаем в случае отсутствия свободной памяти 
        return NULL;
    }
    for (i=0; i<__FD_SETSIZE; i++){
        fd_set_arr[i].sendbuf_id=0LL;
        init_rwsem(&fd_set_arr[i].mutex);
    }
    return fd_set_arr;
}


код на котором собственно происходит подвисание:
    fd_set_item_t*fd_set_arr=fd_set_arr_new();


   for (i=0; i<__FD_SETSIZE; i++)  if(fd_set_arr[i].fd == fd && fd_set_arr[i].sendbuf_id) {
        send_buf_t*sendbuf;

        if(!(sendbuf=get_fd_send_buf(fd))){
            printk(__func__":%ld:Internal programm error:can't found sendbuf for tracked fd=%d\n",(long)current->pid,fd);//ругаемся
            goto out;
        }

        printk(__func__":%ld:i=%u try lock fd_set_arr[i].mutex\n",(long)current->pid,i);
        down_write(&fd_set_arr[i].mutex);//ПОДВИСАЕТ ЗДЕСЬ
        fd_set_arr[i].sendbuf_id=0LL;
        fd_set_arr[i].fd=-1;
        up_write(&fd_set_arr[i].mutex);
        printk(__func__":%ld:i=%u fd_set_arr[i].mutex unlocked\n",(long)current->pid,i);

        printk(__func__":%ld:try lock sendbuf->mutex\n",(long)current->pid);
        down(&sendbuf->mutex);
        if(sendbuf->id){
            if( sendbuf->use_counter)sendbuf->use_counter--;
            if(!sendbuf->use_counter)sendbuf->id=0LL;
        }
        up(&sendbuf->mutex);
        printk(__func__":%ld:sendbuf->mutex unlocked\n",(long)current->pid);
        return;
    }

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

вопрос снят, заработало всё

cvv ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.