системный вызов

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

системный вызов

Anton Maksimenkov-2
Hi all.

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

Сделаю простейший сисколл вот типа такого:
int sys_hello(proc *p, void *v, register_t *retval) {
 printf("Hello World\n");
 return (0);
}

Потом его вызываю в своей проге (она форкает много процессов, и они
часто вызывают данный сисколл):
int main(int argc, char **argv) {
 . . .
 syscall(400);
 . . .
}
Этот мой системный вызов (sys_hello) пока что полностью MP-safe, да?

Как я понял из предыдущего краткого экскурса в SMP, при исполнении
любого сисколла будет захватываться биглок. То есть если у меня один
процесс вызывает данный сисколл, входит в него (и захватывает биглок),
а потом второй процесс (на другом процессоре) тоже его вызывает -
получится так, что второй процесс заблокируется в попытке захватить
биглок и будет висеть, до тех пор пока первый не отработает и не
отпустит биглок.

Так вот, я хочу сделать так, чтобы мой этот сисколл не хватал биглок,
то есть чтобы все его параллельные вызовы из разных процесСОВ (сидящих
на разных процесСОРАХ) могли параллельно же исполняться на разных
процесСОРАХ.

Есть где-то простой способ указать, что некий сискол можно вызывать
без захвата биглока? Я вообще-то не уверен что это вообще возможно,
т.к. тут уже говорилось такое:
> Чтобы запустился ядерный код, нужно либо прерывание, либо исключение. В
> обоих случаях перед входом в обработчик ядро пытается захватить
> глобальный лок. ... Таким образом
> в данный момент времени только один процессор может исполнять код ядра.
> Все остальные могут исполнять или пользовательские инструкции, или
> висеть в спинлоках, ожидая свою очередь войти в ядро.
И у меня, конечно, есть смутное понимание, что между моментом когда
процесс вызовет мой сисколл и моментом когда ядро собсно зайдёт в мою
функцию sys_hello(), будет ещё чего-то делаться внтуриядерное. И это
"ещё чего-то", очень подозреваю, обязательно потребует биглок.

Хорошо, если первый вариант совершенно не возможен, то может быть
такой вариант. Как опять же говорилось:
> биглок (он же kernel_lock) разграничивает доступ к ядру...
> отдать его можно явно вызвав KERNEL_PROC_UNLOCK в контексте процесса.

То есть, я так понимаю, что "в контексте процесса" в данном случае
означало что "НЕ в контексте прерывания". И если я преобразую мой
сискол примерно к такому вот виду:
int sys_hello(proc *p, void *v, register_t *retval) {
 KERNEL_PROC_UNLOCK
 . . .
 printf("Hello World\n");
 . .
 KERNEL_PROC_LOCK
 return (0);
}
то всё что между KERNEL_PROC_UNLOCK/KERNEL_PROC_LOCK сможет и будет
выполняться параллельно на разных процессорах? Ну то есть когда
происходит N параллельных вызовов моего сисколла от N процессов,
выполняющихся на N разных процессорах.

Или всё наоборот и нужно как раз делать KERNEL_PROC_LOCK там где
делается что-то критическое а после этого KERNEL_PROC_UNLOCK? В
исходниках ядра встречал как раз вариант LOCK-секция-UNLOCK.
Можно как-то узнать (внутри сисколла) в каком состоянии биглок -
"захвачен мною" или не захвачен (отпущен)?


P.S. Я чесно говоря не представляю как вообще отследить в каком виде
всё это будет исполняться (параллельно на процессорах или нет), ни в
первоначальном виде сисколла, ни этих LOCK/UNLOCK. И результат
принимаю "на веру".
P.P.S. Или сразу в tech@...?

--
engineer
Reply | Threaded
Open this post in threaded view
|

Re: системный вызов

Mike Belopuhov
On Sun, Feb 15, 2009 at 14:28 +0300, engineer wrote:
> Hi all.
>
> Хочу попробовать поразвлекаться на тему SMP и т.п.
>

давайте давайте, может идею какую родите, как нам потихоньку от
биглоцка избавится.
 

> Сделаю простейший сисколл вот типа такого:
> int sys_hello(proc *p, void *v, register_t *retval) {
>  printf("Hello World\n");
>  return (0);
> }
>
> Потом его вызываю в своей проге (она форкает много процессов, и они
> часто вызывают данный сисколл):
> int main(int argc, char **argv) {
>  . . .
>  syscall(400);
>  . . .
> }
> Этот мой системный вызов (sys_hello) пока что полностью MP-safe, да?
>

MP-safe это не когда код исполняется параллельно, а когда, будучи
исполняемым в параллель, учитывает конкурентный доступ к пользуемым
ресурсам.  То есть если ваш сисколл не обращается к данным, отличным
от локального стека, то он MP-safe по определению, потому что никакой
гонки ни за какие ресурсы нет.  Если же вы начнете вызывать pool_get
или malloc или трогать какие-то структуры ядра, необходимым будет
использование локов.
 

> Как я понял из предыдущего краткого экскурса в SMP, при исполнении
> любого сисколла будет захватываться биглок. То есть если у меня один
> процесс вызывает данный сисколл, входит в него (и захватывает биглок),
> а потом второй процесс (на другом процессоре) тоже его вызывает -
> получится так, что второй процесс заблокируется в попытке захватить
> биглок и будет висеть, до тех пор пока первый не отработает и не
> отпустит биглок.
>
> Так вот, я хочу сделать так, чтобы мой этот сисколл не хватал биглок,
> то есть чтобы все его параллельные вызовы из разных процесСОВ (сидящих
> на разных процесСОРАХ) могли параллельно же исполняться на разных
> процесСОРАХ.
>
> Есть где-то простой способ указать, что некий сискол можно вызывать
> без захвата биглока? Я вообще-то не уверен что это вообще возможно,

указать флаг SY_NOLOCK как это сделано для getpid (kern/init_sysent.c):

        { 0, 0, SY_NOLOCK | 0,
            sys_getpid },                       /* 20 = getpid */


> т.к. тут уже говорилось такое:
> > Чтобы запустился ядерный код, нужно либо прерывание, либо исключение. В
> > обоих случаях перед входом в обработчик ядро пытается захватить
> > глобальный лок. ... Таким образом
> > в данный момент времени только один процессор может исполнять код ядра.
> > Все остальные могут исполнять или пользовательские инструкции, или
> > висеть в спинлоках, ожидая свою очередь войти в ядро.
> И у меня, конечно, есть смутное понимание, что между моментом когда
> процесс вызовет мой сисколл и моментом когда ядро собсно зайдёт в мою
> функцию sys_hello(), будет ещё чего-то делаться внтуриядерное. И это
> "ещё чего-то", очень подозреваю, обязательно потребует биглок.
>

посмотрите в syscall() в arch/i386/i386/trap.c.
 
> Хорошо, если первый вариант совершенно не возможен, то может быть
> такой вариант. Как опять же говорилось:
> > биглок (он же kernel_lock) разграничивает доступ к ядру...
> > отдать его можно явно вызвав KERNEL_PROC_UNLOCK в контексте процесса.
>
> То есть, я так понимаю, что "в контексте процесса" в данном случае
> означало что "НЕ в контексте прерывания".

в контексте прерывания оно же называется KERNEL_LOCK (а еще ниже
и подавно LOCK_KERNEL), хотя это те же операции над тем же
kernel_lock'ом, дефайнов уйму развели просто.

> И если я преобразую мой
> сискол примерно к такому вот виду:
> int sys_hello(proc *p, void *v, register_t *retval) {
>  KERNEL_PROC_UNLOCK
>  . . .
>  printf("Hello World\n");
>  . .
>  KERNEL_PROC_LOCK
>  return (0);
> }
> то всё что между KERNEL_PROC_UNLOCK/KERNEL_PROC_LOCK сможет и будет
> выполняться параллельно на разных процессорах? Ну то есть когда
> происходит N параллельных вызовов моего сисколла от N процессов,
> выполняющихся на N разных процессорах.
>

да, только брать его обратно и не надо.
 
> Или всё наоборот и нужно как раз делать KERNEL_PROC_LOCK там где
> делается что-то критическое а после этого KERNEL_PROC_UNLOCK? В
> исходниках ядра встречал как раз вариант LOCK-секция-UNLOCK.
> Можно как-то узнать (внутри сисколла) в каком состоянии биглок -
> "захвачен мною" или не захвачен (отпущен)?
>

можно (это делает для себя sched_lock кстати):

        if (__mp_lock_held(&kernel_lock)) {
                say "meh!";
        }

>
> P.S. Я чесно говоря не представляю как вообще отследить в каком виде
> всё это будет исполняться (параллельно на процессорах или нет), ни в
> первоначальном виде сисколла, ни этих LOCK/UNLOCK. И результат
> принимаю "на веру".

проблема MP в том, что человеку трудно думать так как работает MP
компутер.  вообще говоря, все производители железа заранее знали
что SMP это болото и резон был только срубить денег, а сейчас
глядишь всякие ниагары полезли.

> P.P.S. Или сразу в tech@...?
>

в техе тоже мы с гранжиком сидим, арт всё равно отвечать не станет :-)
 
> --
> engineer


Reply | Threaded
Open this post in threaded view
|

Re: системный вызов

Alexander Yurchenko-3
In reply to this post by Anton Maksimenkov-2
On Sun, Feb 15, 2009 at 02:28:29PM +0300, engineer wrote:

> Hi all.
>
> Хочу попробовать поразвлекаться на тему SMP и т.п.
>
> Сделаю простейший сисколл вот типа такого:
> int sys_hello(proc *p, void *v, register_t *retval) {
>  printf("Hello World\n");
>  return (0);
> }
>
> Потом его вызываю в своей проге (она форкает много процессов, и они
> часто вызывают данный сисколл):
> int main(int argc, char **argv) {
>  . . .
>  syscall(400);
>  . . .
> }
> Этот мой системный вызов (sys_hello) пока что полностью MP-safe, да?

Да, так как в printf(9) есть мьютекс. Если б его там не было, то даже
такой простой сискол уже был бы не mp-safe.

> --
> engineer

--
   Alexander Yurchenko


Reply | Threaded
Open this post in threaded view
|

Re: системный вызов

Stanislav Kruchinin
In reply to this post by Anton Maksimenkov-2
engineer wrote:
>
> Как я понял из предыдущего краткого экскурса в SMP, при исполнении
> любого сисколла будет захватываться биглок. То есть если у меня один
> процесс вызывает данный сисколл, входит в него (и захватывает биглок),
> а потом второй процесс (на другом процессоре) тоже его вызывает -
> получится так, что второй процесс заблокируется в попытке захватить
> биглок и будет висеть, до тех пор пока первый не отработает и не
> отпустит биглок.
>

В императивном программировании от MP одно горе. Вместо того, чтобы решать свою
задачу, людям приходится думать о блокировках, гонках, семафорах, мьютексах и
прочем бреде. Даже элементарный printf нельзя сделать без мьютекса. Там, где
реально нужен параллелизм (коммутация, маршрутизация, per-user QoS), ОС общего
назначения будут вытеснены специализированными решениями, вроде ATM-коммутаторов
Ericsson или SSL-акселераторов Nortel, реализованными на функциональных языках.


Reply | Threaded
Open this post in threaded view
|

Re: системный вызов

Alexander Yurchenko-3
On Mon, Feb 16, 2009 at 05:36:05AM +0300, Stanislav Kruchinin wrote:
> В императивном программировании от MP одно горе. Вместо того, чтобы решать свою
> задачу, людям приходится думать о блокировках, гонках, семафорах, мьютексах и
> прочем бреде. Даже элементарный printf нельзя сделать без мьютекса. Там, где
> реально нужен параллелизм (коммутация, маршрутизация, per-user QoS), ОС общего
> назначения будут вытеснены специализированными решениями, вроде ATM-коммутаторов
> Ericsson или SSL-акселераторов Nortel, реализованными на функциональных языках.

На Эрланге можно писать и на обычном писюке :)

--
   Alexander Yurchenko


Reply | Threaded
Open this post in threaded view
|

Re: системный вызов

Stanislav Kruchinin
Alexander Yurchenko wrote:
>
> На Эрланге можно писать и на обычном писюке :)
>

Можно, но это имеет смысл в основном для распределенных веб-приложений, не
требующих большой производительности, в отличие от телекомовских задач.


Reply | Threaded
Open this post in threaded view
|

Re: системный вызов

Dinar Talypov
On Mon, 16 Feb 2009 09:04:07 +0300
Stanislav Kruchinin <[hidden email]> wrote:

> Alexander Yurchenko wrote:
> >
> > На Эрланге можно писать и на обычном писюке :)
> >
>
> Можно, но это имеет смысл в основном для распределенных веб-приложений, не
> требующих большой производительности, в отличие от телекомовских задач.
>

Для телекома серьезное только FPGA-железки, хотя это редкость, т.к.
для проектирования такого железа требуются знания и время. Большая часть железок на
рынке телекома это PC, только с разными лейблами.

Хотя все это уже офтопик :)


--
Динар Талыпов