Rocksolid Light

groups  faq  privacy  How to post  login

Message-ID:  

Don't you wish you had more energy... or less ambition?


rocksolid / de.comp.os.unix.programming / Re: SysV-Semapor Set mit zwei Semaphoren

SubjectAuthor
* SysV-Semapor Set mit zwei SemaphorenBonita Montero
`- Re: SysV-Semapor Set mit zwei SemaphorenBonita Montero

1
Subject: SysV-Semapor Set mit zwei Semaphoren
From: Bonita Montero
Newsgroups: de.comp.os.unix.programming
Organization: A noiseless patient Spider
Date: Wed, 8 Nov 2023 12:56 UTC
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder2.eternal-september.org!news.eternal-september.org!raubtier-asyl.eternal-september.org!.POSTED!not-for-mail
From: Bonita.M...@gmail.com (Bonita Montero)
Newsgroups: de.comp.os.unix.programming
Subject: SysV-Semapor Set mit zwei Semaphoren
Date: Wed, 8 Nov 2023 13:56:37 +0100
Organization: A noiseless patient Spider
Lines: 99
Message-ID: <uig0i5$1js68$1@raubtier-asyl.eternal-september.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Wed, 8 Nov 2023 12:56:37 -0000 (UTC)
Injection-Info: raubtier-asyl.eternal-september.org; posting-host="8087a75e9a50340a40d90ff08d823f7b";
logging-data="1700040"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/Yw/QeSiXSLNyBvU5a1lt6lvH38v/9LsY="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:BDAQqP8jiS785xhAxNQ9RDm6qYE=
Content-Language: de-DE
View all headers

Ich habe mir eine Monitor-Klasse, ähnlich der Monitore in Java oder
..NET geschrieben. Das Besondere daran ist, dass das Annehmens einer
Signalisierung (notify() / notify_all()) durch einen anderne Thread
und das Locken des dazugehörigen Mutex nur ein Schitt bzw. ein Ker-
nel-Aufruf ist. Unter Win32 kann man auf nahezu jede Art von Kernel
-Objjekten warten, sogar auf mehrere bzw. darauf, dass eines oder
alle Kernel-Objekte signalisiert weden. Ich habe an der Stelle dann
ein sog. Event (binäres Semaphore von Win32) das signalisiert, dass
ein Thread den kritischen Abschnitt betreten darf und ein Semaphor
das signalisiert das jemand notify() oder notify_all() gesagt hat.
Das Locken des kritischen Abschnitts findet ohne, dass jemand anders
gerade den Mutex-Anteil des Monitors hält über ein atomic<> komplett
im Userspace statt. Gibt es aber einen anderen Thread der den Mutex
hält legen sich die darauffolgenden schlafen und werden über das
Event einzeln geweckt wenn ein anderer Thread den kritischen Ab-
schnitt verlässt.
Wenn jemand wait() sagt muss das während des Haltens des Mutex ge-
schehen und verlässt damit implizit den kritischen Abschnitt und
wartet darauf auf das Mutex zum Betreten des kritischen Abschnitts
sowie das Semaphor das über das notify()-/notify_all()-Ereignis
benachrichtigt. "Drückt" jemand notify() dann wird das Semaphor
nur um Eins hochgezählt, wenn jemand notify_all() "drückt" werden
so viele Threads losgetreten wie sich im Kernel mit einem wait()
schlafengelegen haben.
Mit Win32 funktioniert das alles einwandfrei. Bzw. unter Win32 kann
ich ja einfach beim Eintreten in den kritischen Abschnitt während
jemand anders gerade dran ist einfach WaitForSingleObject() auf das
Event sagen und beim wait() WaitForMultipleObjects() auf das Event
*und* das zählende Semaphor zum Benachrichtigen der wait()er.
Unter Linux hat man nicht so flexible Möglichkeiten, auf die Benach-
richtigung nahezu beliebiger Kernel-Ereignisse zu warten. Aber es
gibt System-V-Semaphore, die nicht nur einzelne Semaphore repräsen-
tieren, sondern ein ganzes Set von Semaphoren. Damit wäre es dann
sogar möglich, auf ein Semaphor in diesem Set zu warten und atomar
gleichzeitig ein anderes hochzuzählen. Das macht man mit der Funk-
tion semop(), der man ein Array von Operationen auf dieses Set gibt.
Soweit ich das jetzt verstanden habe müssen nicht alle Operationen
in diesem Array sich auf alle Semaphore des Set beziehen, bzw. man
kann einzelne davon auch links liegen lassen. Habe ich also zwei
Seamphoren in dem Set und nutze nur eins in diesem Operations-Array
wird das andere nicht adressiert, und man weckt oder wartet nur auf
das was adressiert ist. Ist meine Annahme da richtig ?
Auf jeden Fall habe ich mir ein kleines C++20-Beispiel-Programm
geschrieben das man mit ein wenig Intuition auch mit C-Kenntnissen
nachvollziehen kann. Ich kreiere dabei zwei Semaphore-Sets mit je
zwei Semaphoren und setze anfänglich nur die beiden Semaphoreen
eines Sets, und das nicht mit einem semop-Array von zwei Elementen,
sondern jeweils einzeln, um den Fall zu simulieren, dass der Mutex
-Teil und der wait()-Teil des Sets separat losgetreten werden.
Dann starte ich jeweils zwei Threads die beide jeweils auf beide
Semaphore des Sets warten und dann beide beide Mutexe des jeweils
anderen Sets signalisieren.
Hier ist der C++20-Code, der zu meinem Überraschen nicht funktio-
nierte:

#include <thread>
#include <initializer_list>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/stat.h>

using namespace std;

int main()
{ int
setA = semget( IPC_PRIVATE, 2, S_IRUSR | S_IWUSR ),
setB = semget( IPC_PRIVATE, 2, S_IRUSR | S_IWUSR );
if( setA == -1 || setB == -1 )
return EXIT_FAILURE;
static auto xSemop = []( int set, std::initializer_list<sembuf> sems )
{
int ret;
while( (ret = ::semop( set, const_cast<sembuf *>(sems.begin()),
sems.size() )) == EINTR );
return ret;
};
if( xSemop( setA, { { 0, 1, 0 } } ) || xSemop( setA, { { 1, 1, 0 } } ) )
return EXIT_FAILURE;
constexpr size_t ROUNDS = 1'000'000;
auto thr = []( int mySet, int yourSet )
{
for( size_t r = ROUNDS; r--; )
if( xSemop( mySet, { { 0, -1, 0 }, { 1, -1, 0 } } )
|| xSemop( yourSet, { { 0, 1, 0 }, { 1, 1, 0 } } ) )
terminate();
};
jthread
thrA( thr, setA, setB ),
thrB( thr, setB, setA );
}

xSemop ist nur eine handlicher Variante von semop der ich eine
initializer_list<sembuf> gebe, was in Prinzip nur ein Start- und
Ende-Pointer ist; dass hat den Vorteil, dass ich den Parameter
mit einer C++11 uniform-initialization füttern kann, also nicht
ein einzelnes sembuf-Array wie in C dafür anlegen muss, sondern
im Aufruf direkt das angeben kann was ich für die C-Array Initia-
lisierung angeben müsste.

Subject: Re: SysV-Semapor Set mit zwei Semaphoren
From: Bonita Montero
Newsgroups: de.comp.os.unix.programming
Organization: A noiseless patient Spider
Date: Wed, 8 Nov 2023 13:56 UTC
References: 1
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder2.eternal-september.org!news.eternal-september.org!raubtier-asyl.eternal-september.org!.POSTED!not-for-mail
From: Bonita.M...@gmail.com (Bonita Montero)
Newsgroups: de.comp.os.unix.programming
Subject: Re: SysV-Semapor Set mit zwei Semaphoren
Date: Wed, 8 Nov 2023 14:56:25 +0100
Organization: A noiseless patient Spider
Lines: 108
Message-ID: <uig428$1kftd$2@raubtier-asyl.eternal-september.org>
References: <uig0i5$1js68$1@raubtier-asyl.eternal-september.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Wed, 8 Nov 2023 13:56:24 -0000 (UTC)
Injection-Info: raubtier-asyl.eternal-september.org; posting-host="8087a75e9a50340a40d90ff08d823f7b";
logging-data="1720237"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19AhJraO6sZ64raBvQvvTrXqb7jYGypgoY="
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:FUP1INvpkkhnxC1bx3drajs1tkY=
Content-Language: de-DE
In-Reply-To: <uig0i5$1js68$1@raubtier-asyl.eternal-september.org>
View all headers

Ich hab's: ich wenn ich einen Semaphor hoochzähle IPC_NOWAIT angeben.
Wer denkt sich sowas aus ? IPC_NOWAIT sollte doch nur nötig sein wenn
ich das Semaphor runterzähle und darauf warte, dass jemand anders das
Seamphor hochzählt. Das Lostreten eines anderen Threads ist ja eigent-
lich komplett asynchron.

Am 08.11.2023 um 13:56 schrieb Bonita Montero:
> Ich habe mir eine Monitor-Klasse, ähnlich der Monitore in Java oder
> .NET geschrieben. Das Besondere daran ist, dass das Annehmens einer
> Signalisierung (notify() / notify_all()) durch einen anderne Thread
> und das Locken des dazugehörigen Mutex nur ein Schitt bzw. ein Ker-
> nel-Aufruf ist. Unter Win32 kann man auf nahezu jede Art von Kernel
> -Objjekten warten, sogar auf mehrere bzw. darauf, dass eines oder
> alle Kernel-Objekte signalisiert weden. Ich habe an der Stelle dann
> ein sog. Event (binäres Semaphore von Win32) das signalisiert, dass
> ein Thread den kritischen Abschnitt betreten darf und ein Semaphor
> das signalisiert das jemand notify() oder notify_all() gesagt hat.
> Das Locken des kritischen Abschnitts findet ohne, dass jemand anders
> gerade den Mutex-Anteil des Monitors hält über ein atomic<> komplett
> im Userspace statt. Gibt es aber einen anderen Thread der den Mutex
> hält legen sich die darauffolgenden schlafen und werden über das
> Event einzeln geweckt wenn ein anderer Thread den kritischen Ab-
> schnitt verlässt.
> Wenn jemand wait() sagt muss das während des Haltens des Mutex ge-
> schehen und verlässt damit implizit den kritischen Abschnitt und
> wartet darauf auf das Mutex zum Betreten des kritischen Abschnitts
> sowie das Semaphor das über das notify()-/notify_all()-Ereignis
> benachrichtigt. "Drückt" jemand notify() dann wird das Semaphor
> nur um Eins hochgezählt, wenn jemand notify_all() "drückt" werden
> so viele Threads losgetreten wie sich im Kernel mit einem wait()
> schlafengelegen haben.
> Mit Win32 funktioniert das alles einwandfrei. Bzw. unter Win32 kann
> ich ja einfach beim Eintreten in den kritischen Abschnitt während
> jemand anders gerade dran ist einfach WaitForSingleObject() auf das
> Event sagen und beim wait() WaitForMultipleObjects() auf das Event
> *und* das zählende Semaphor zum Benachrichtigen der wait()er.
> Unter Linux hat man nicht so flexible Möglichkeiten, auf die Benach-
> richtigung nahezu beliebiger Kernel-Ereignisse zu warten. Aber es
> gibt System-V-Semaphore, die nicht nur einzelne Semaphore repräsen-
> tieren, sondern ein ganzes Set von Semaphoren. Damit wäre es dann
> sogar möglich, auf ein Semaphor in diesem Set zu warten und atomar
> gleichzeitig ein anderes hochzuzählen. Das macht man mit der Funk-
> tion semop(), der man ein Array von Operationen auf dieses Set gibt.
> Soweit ich das jetzt verstanden habe müssen nicht alle Operationen
> in diesem Array sich auf alle Semaphore des Set beziehen, bzw. man
> kann einzelne davon auch links liegen lassen. Habe ich also zwei
> Seamphoren in dem Set und nutze nur eins in diesem Operations-Array
> wird das andere nicht adressiert, und man weckt oder wartet nur auf
> das was adressiert ist. Ist meine Annahme da richtig ?
> Auf jeden Fall habe ich mir ein kleines C++20-Beispiel-Programm
> geschrieben das man mit ein wenig Intuition auch mit C-Kenntnissen
> nachvollziehen kann. Ich kreiere dabei zwei Semaphore-Sets mit je
> zwei Semaphoren und setze anfänglich nur die beiden Semaphoreen
> eines Sets, und das nicht mit einem semop-Array von zwei Elementen,
> sondern jeweils einzeln, um den Fall zu simulieren, dass der Mutex
> -Teil und der wait()-Teil des Sets separat losgetreten werden.
> Dann starte ich jeweils zwei Threads die beide jeweils auf beide
> Semaphore des Sets warten und dann beide beide Mutexe des jeweils
> anderen Sets signalisieren.
> Hier ist der C++20-Code, der zu meinem Überraschen nicht funktio-
> nierte:
>
> #include <thread>
> #include <initializer_list>
> #include <sys/types.h>
> #include <sys/sem.h>
> #include <sys/stat.h>
>
> using namespace std;
>
> int main()
> {
>     int
>         setA = semget( IPC_PRIVATE, 2, S_IRUSR | S_IWUSR ),
>         setB = semget( IPC_PRIVATE, 2, S_IRUSR | S_IWUSR );
>     if( setA == -1 || setB == -1 )
>         return EXIT_FAILURE;
>     static auto xSemop = []( int set, std::initializer_list<sembuf> sems )
>     {
>         int ret;
>         while( (ret = ::semop( set, const_cast<sembuf *>(sems.begin()),
> sems.size() )) == EINTR );
>         return ret;
>     };
>     if( xSemop( setA, { { 0, 1, 0 } } ) || xSemop( setA, { { 1, 1, 0 }
> } ) )
>         return EXIT_FAILURE;
>     constexpr size_t ROUNDS = 1'000'000;
>     auto thr = []( int mySet, int yourSet )
>     {
>         for( size_t r = ROUNDS; r--; )
>             if( xSemop( mySet, { { 0, -1, 0 }, { 1, -1, 0 } } )
>                 || xSemop( yourSet, { { 0, 1, 0 }, { 1, 1, 0 } } ) )
>                 terminate();
>     };
>     jthread
>         thrA( thr, setA, setB ),
>         thrB( thr, setB, setA );
> }
>
> xSemop ist nur eine handlicher Variante von semop der ich eine
> initializer_list<sembuf> gebe, was in Prinzip nur ein Start- und
> Ende-Pointer ist; dass hat den Vorteil, dass ich den Parameter
> mit einer C++11 uniform-initialization füttern kann, also nicht
> ein einzelnes sembuf-Array wie in C dafür anlegen muss, sondern
> im Aufruf direkt das angeben kann was ich für die C-Array Initia-
> lisierung angeben müsste.


rocksolid / de.comp.os.unix.programming / Re: SysV-Semapor Set mit zwei Semaphoren

1
server_pubkey.txt

rocksolid light 0.9.136
clearnet tor