Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«QNX/UNIX: Анатомия ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΠ·ΠΌΠ°Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 63

Автор Π¦ΠΈΠ»ΡŽΡ€ΠΈΠΊ ОлСг Π˜Π²Π°Π½ΠΎΠ²ΠΈΡ‡

static bool debug = false;

static char* str;

static volatile int ind = 0;

void* threadfunc(void* data) {

Β pthread_barrier_wait(&bstart);

Β unsigned long i = 0;

Β char tid[8];

Β sprintf(tid, "%d", pthread_self());

Β uint64_t t = 0, t1;

Β while (i++ != N) {

Β  t1 = ClockCycles();

Β  pthread_mutex_lock(&mutex);

Β  if (debug) str[ind++] = *tid;

Β  pthread_mutex_unlock(&mutex);

Β  t += ClockCycles() - t1;

Β  sched_yield();

Β }

Β cout << pthread_self() << "\t: cycles - "

Β  << t << ", on mutex - " << t / N << endl;

Β return NULL;

}

int main(int argc, char *argv[]) {

Β int opt, val;

Β while ((opt = getopt(argc, argv, "n,v")) != -1) {

Β Β switch (opt) {

Β Β  case 'n':

Β Β  if (sscanf(optarg, "%i", &val) != 1)

Β Β Β  cout << "parse command line error" << endl, exit(EXIT_FAILURE);

Β Β  if (val > 0) N = val;

Β Β  break;

Β  case 'v':

Β Β  debug = true;

Β Β  break;

Β  default:

Β Β  exit(EXIT_FAILURE);

Β  }

Β }

Β if (debug) str = new char[2 * N + 1];

Β const int T = 2;

Β pthread_t tid[T];

Β if (pthread_barrier_init(&bstart, NULL, T) != EOK)

Β  perror("barrier init"), exit(EXIT_FAILURE);

Β for (int i = 0; i < T; i++)

Β  if (pthread_create(tid + i, NULL, threadfunc, NULL) != EOK)

Β Β  perror("thread create"), exit(EXIT_FAILURE);

Β for (int i = 0; i < T; i++)

Β  pthread_join(tid[i], NULL);

Β if (debug) {

Β  str[ind] = '\0';

Β  cout << str << endl;

Β  delete [] str;

Β }

Β exit(EXIT_SUCCESS);

}

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ выполнСния этого тСста:

# sy20m -n100000

3Β Β Β Β Β Β  : cycles - 14644442, on mutex - 146

2Β Β Β Β Β Β Β : cycles - 14614219; on mutex - 146

# sy20m -n1000000

3Β Β Β Β Β Β  : cycles - 146505047; on mutex - 146

2Β Β Β Β Β Β  : cycles - 146388673; on mutex - 146

ΠœΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΡƒΠ΅ΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ вмСсто ΠΌΡŒΡŽΡ‚Π΅ΠΊΡΠ° Π½Π΅ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ Π±ΠΈΠ½Π°Ρ€Π½Ρ‹ΠΉ сСмафор. Для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π·Π°Π³Ρ€ΠΎΠΌΠΎΠΆΠ΄Π°Ρ‚ΡŒ тСкст практичСски Ρ‚Π΅ΠΌ ΠΆΠ΅ ΠΊΠΎΠ΄ΠΎΠΌ, пСрСчислим Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΡ€ΠΈ этом измСнСния ( Ρ„Π°ΠΉΠ» sy20s.cc):

1. ВмСсто ΠΌΡŒΡŽΡ‚Π΅ΠΊΡΠ° объявляСм Π½Π΅ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ сСмафор, Π° статичСская инициализация ΠΌΡŒΡŽΡ‚Π΅ΠΊΡΠ° замСняСтся Π½Π° ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ (Π² Ρ‚Π΅Π»Π΅ Π³Π»Π°Π²Π½ΠΎΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹) динамичСской ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ сСмафора с присвоСниСм Π΅ΠΌΡƒ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ значСния 1:

static sem_t sem;

...

if (sem_init(&sem, 0, 1) != 0)

Β perror("semaphore init"), exit(EXIT_FAILURE);

2. Ѐункция ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π²ΠΈΠ΄:

void* threadfunc(void* data) {

Β ...

Β while (i++ != N) {

Β  t1 = ClockCycles();

Β  sem_wait(&sem);

Β  if (debug) str[ind++] = *tid;

Β  sem_post(&sem);

Β  t += ClockCycles() - t1;

Β  sched_yield();

Β }

Β ...

}

Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ исполнСния Π½Π° этот Ρ€Π°Π· ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ:

# sy20s -n100000

3Β Β Β Β Β Β  : cycles - 87048886; on semaphore - 870

2Β Β Β Β Β Β  : cycles - 87077787; on semaphore - 870

# sy20s -n1000000

3Β Β Β Β Β Β  : cycles - 869638168; on semaphore β€” 869

2Β Β Β Β Β Β  : cycles - 868725494, on semaphore - 868

Π”Π΅Π»Π°Π΅ΠΌ послСднюю ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡŽ Π² этой Π³Ρ€ΡƒΠΏΠΏΠ΅ тСстов, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ спСцифику ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ сСмафора ( Ρ„Π°ΠΉΠ» sy20n.cc):

1. ВмСсто ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° динамичСской ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π½Π΅ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ сСмафора ΠΌΡ‹ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ сСмафор:

static sem_t* sem;

...

const char semname[] = "/duble";

if ((sem = sem_open(semname, O_CREAT, S_IRWX0, 1)) == SEM_FAILED)

Β perror("semaphore init"), exit(EXIT_FAILURE);

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

ПослСдний ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ заслуТиваСт ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ коммСнтария. ВСхничСская докумСнтация ΡƒΡ‚Π²Π΅Ρ€ΠΆΠ΄Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ функция

sem_open()
, Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‰Π°Ρ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ созданного дСскриптора сСмафора Ρ‚ΠΈΠΏΠ°
sem_t
, Π² случаС ошибки Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ -1 (Ρ‚Π°ΠΊ Π±Ρ‹Π»ΠΎ записано ΠΈ Π² самых Ρ€Π°Π½Π½ΠΈΡ… рСдакциях POSIX). Но использованиС конструкции Π²ΠΈΠ΄Π°:

if (sem_open( ... ) == -1)

просто Π²Ρ‹Π·ΠΎΠ²Π΅Ρ‚ ΡΠΈΠ½Ρ‚Π°ΠΊΡΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΡˆΠΈΠ±ΠΊΡƒ (нСсоотвСтствиС Ρ‚ΠΈΠΏΠΎΠ²) ΠΈ Π½Π΅ ΠΏΡ€ΠΎΠΉΠ΄Π΅Ρ‚ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡ†ΠΈΡŽ! ЕстСствСннСС Π±Ρ‹Π»ΠΎ Π±Ρ‹ для Ρ‚Π°ΠΊΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ

NULL
Π² случаС ошибки, Π½ΠΎ... Ρ‚Π°ΠΊ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΎ Π² POSIX. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… рСализациях UNIX опрСдСляСтся константа:

#define SEM_FAILED ((sem_t*)(-1))

Π’ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ QNX ΠΎΠ½Π° Π½ΠΈΠ³Π΄Π΅ Π½Π΅ упоминаСтся, Π½ΠΎ, ΠΊΠ°ΠΊ ΠΌΡ‹ Π²ΠΈΠ΄ΠΈΠΌ, ΠΎΠ½Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π°, ΠΈ всС прСкрасно Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚!