Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

232
Views
¿Cómo crear una demora precisa de nanosegundos en un pthread y cómo ejecutar una parte del pthread del programa sin interrupción?

Soy un principiante en la programación C. En el siguiente código, tenemos dos pthreads. Quiero que uno de ellos se retrase a elección del usuario después de sincronizar los dos pthreads. Quiero que este retraso sea lo más preciso posible. En el siguiente código he hecho esto pero no ocurre la cantidad exacta de retraso.

Pero también tengo otra pregunta, y es cómo puedo obligar a un pthread a ejecutar cierta parte del programa de principio a fin sin interrupción.

Gracias de antemano.

código:

 #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <sys/random.h> #include <sys/time.h> #include <math.h> pthread_cond_t cond; pthread_mutex_t cond_mutex; unsigned int waiting; struct timeval timeZero, timeOne, timeZeroBase, timeOneBase; struct timespec tim, tim2; int flag = 0; void synchronize(void) { pthread_mutex_lock(&cond_mutex); if (++waiting == 2) { pthread_cond_broadcast(&cond); } else { while (waiting != 2) pthread_cond_wait(&cond, &cond_mutex); } pthread_mutex_unlock(&cond_mutex); } void *threadZero(void *_) { // ... synchronize(); gettimeofday(&timeZeroBase, 0); if(flag == 0) nanosleep(&tim, &tim2); gettimeofday(&timeZero, 0); timeZero.tv_usec = timeZero.tv_usec - timeZeroBase.tv_usec; // ... return NULL; } void *threadOne(void *_) { // ... synchronize(); gettimeofday(&timeOneBase, 0); if(flag == 1) nanosleep(&tim, &tim2); gettimeofday(&timeOne, 0); timeOne.tv_usec = timeOne.tv_usec - timeOneBase.tv_usec; // ... return NULL; } int main(void) { pthread_t zero, one; tim.tv_sec = 0; tim.tv_nsec = 50; printf("Declare the number of function (0 or 1): "); scanf("%d", &flag); pthread_create(&zero, NULL, threadZero, NULL); pthread_create(&one, NULL, threadOne, NULL); // ... pthread_join(zero, NULL); pthread_join(one, NULL); printf("\nReal delay (ns): %lu\n", (timeZero.tv_usec - timeOne.tv_usec)); return 0; }
over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Una forma de aumentar la precisión es esperar ocupado en lugar de dormir.

Creé una función llamada mysleep que toma una struct timespec* que contiene el tiempo de sueño solicitado. Verifica la hora actual y agrega el tiempo de suspensión solicitado a eso, y luego simplemente gira hasta la hora actual >= el punto objetivo en el tiempo.

Sin embargo, tenga en cuenta: no se garantiza que permanezca dentro de cualquier precisión. A menudo estará bastante bien, pero a veces, cuando el sistema operativo pone el hilo en espera, verá picos en el tiempo medido. Si no tiene suerte, la calibración tendrá uno de estos picos y luego todos sus sueños se apagarán por completo. Puede ejecutar la rutina de calibración 100 veces y luego elegir el valor medio para que esa desafortunada circunstancia sea muy poco probable.

 #include <stdio.h> #include <time.h> static long calib; // used for calibrating mysleep() void mysleep(const struct timespec *req) { struct timespec tp, now; clock_gettime(CLOCK_MONOTONIC, &tp); // get current time point // add the requested sleep time and remove the calibrated value tp.tv_sec += req->tv_sec; tp.tv_nsec += req->tv_nsec - calib; if(tp.tv_nsec > 999999999) { tp.tv_nsec -= 1000000000; ++tp.tv_sec; } else if(tp.tv_nsec<0) { tp.tv_nsec += 1000000000; --tp.tv_sec; } // busy-wait until the target time point is reached: do { clock_gettime(CLOCK_MONOTONIC, &now); } while(now.tv_sec < tp.tv_sec || (now.tv_sec == tp.tv_sec && now.tv_nsec < tp.tv_nsec)); } struct timespec get_diff(const struct timespec *start, struct timespec *end) { struct timespec temp; if((end->tv_nsec - start->tv_nsec) < 0) { temp.tv_sec = end->tv_sec - start->tv_sec - 1; temp.tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec; } else { temp.tv_sec = end->tv_sec - start->tv_sec; temp.tv_nsec = end->tv_nsec - start->tv_nsec; } return temp; } // A non-scientific calibration routine void calibrate() { struct timespec start, end, sleep = {0}; calib = 0; clock_gettime(CLOCK_MONOTONIC, &start); mysleep(&sleep); clock_gettime(CLOCK_MONOTONIC, &end); struct timespec diff = get_diff(&start, &end); calib = (diff.tv_sec * 1000000000 + diff.tv_nsec) / 2; } int main() { calibrate(); // must be done before using mysleep() // use mysleep() }

Manifestación

Salida posible (con un pico):

 calib=157 should be close to 1000: 961 should be close to 1000: 931 should be close to 1000: 906 should be close to 1000: 926 should be close to 1000: 935 should be close to 1000: 930 should be close to 1000: 916 should be close to 1000: 932 should be close to 1000: 124441 should be close to 1000: 911
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!