¿Cómo llamar a una función C desde lugares aleatorios dentro de otra función?

¿Puede alguien decirme cómo insertar una llamada de función (por ejemplo, Yield() ) en lugares aleatorios dentro de una función de C , de modo que cada vez que se ejecuta el código, se llame a Yield() desde diferentes partes del código?

Me enfrento a este requisito, ya que estoy usando 2 subprocesos en un entorno de subprocesos cooperativos , donde, a menos que el subproceso en ejecución ceda explícitamente al procesador, el otro subproceso (en espera) no puede comenzar a ejecutarse. No quiero colocar la llamada Yield() en un solo punto, ya que eso hace que la secuencia de hilos sea determinista. Sin volver a cablear todo el entorno (desde cooperativo a preventivo), esta es la única solución que se me ocurre en la que Thread_1 () hace que el Yield() llame a lugares aleatorios dentro de él, permitiendo que Thread_2 () tome el control.

¡Cualquier información sobre una solución diferente que logre los mismos objectives finales también es bienvenida!

Creo que se necesita una solución BFI.

Creo que tendrás que resolver esto de la manera obvia. Necesitará hacer una envoltura para Yield() que tome una decisión “aleatoria” sobre si llamar o no a la realidad.

Si no está preocupado por la velocidad de ejecución, lo convertiría en una función real de C, y si lo está, le sugiero una macro preprocesadora.

Entonces, algo como:

 #define Yield0() ((random() & 0xf) == 0 && Yield()) 

Elija la máscara para el porcentaje de probabilidad de una llamada que desea. Para 0xf, y si random() tiene una buena aleatoriedad de bits de orden inferior, vería 1 rendimiento () en 16 llamadas. Si puede usar un MT u otro generador de números aleatorios de alta calidad, los bits de orden inferior serán directamente útiles; de lo contrario, querría random() >> 3 & ...

Y solo necesitarás poner llamadas Yield0 () en todas partes.

Definiría una función algo como:

 void maybe_yield() { if (rand() & 0x10) yield(); } 

Luego, maybe_yield() llamadas a maybe_yield() largo de tu código. Dependiendo de la frecuencia con la que desee que se llame al rendimiento, puede cambiar 0x10 a una constante con más bits configurados para obtener el yield() llama con más frecuencia. Aparte de eso, asegúrese de llamar a srand() con un valor que cambie de una ejecución a la siguiente para obtener diferentes secuencias en diferentes ejecuciones.

Opción A: ¿Por qué no llamar a yield() cuando el hilo se atasca? Mejor aún, ¿por qué no encapsular eso en cada operación que podría atascarse?

 int disk_read (...) { begin_io (); while (!io_completed && !timed_out()) yield(); if (timed_out()) // etc. ... } 

Opción B: por lo general, con rendimiento cooperativo, cuando el otro subproceso no está listo para ejecutarse, el yield() es un no-op. Por lo tanto, ponlo en todas partes:

 void thread1 (...) { yield(); do_something_a(); yield(); do_something_b(); yield(); do_something_c(); ... } 

Opción C: Confíe en que los procesadores sean lo suficientemente rápidos y que las cosas ocurran lo suficientemente a menudo como para que los yields() mínimos yields() funcionen bien:

 void thread1 (...) { init(); while (...) { do_heavy_crunching(); yield(); do_something_else(); } } 

En cientos de aplicaciones del mundo real, la Opción C funciona bien. El determinismo suele ayudar, no hiere.

En realidad, cuando se ejecuta en un entorno de subprocesos cooperativos, realmente desea determinismo.

Pero, si estás empeñado en hacerlo, solo necesitas hacerlo al azar.

 #include  // And make sure you seed the generator with srand() somewhere. #define YIELD_CHANCE 15 #define yield Yield #ifdef YIELD_CHANCE #if YIELD_CHANCE > 0 #if YIELD_CHANCE <= 100 #undef yield void yield(void) { if (rand() < (RAND_MAX / (100/YIELD_CHANCE))) Yield(); } #endif #endif #endif 

luego cambie sus llamadas de yield a yield y, dependiendo del valor que YIELD_CHANCE tenga configurado en el momento de la comstackción, obtendrá un comportamiento determinista o no determinista.

Si no existe o está fuera del rango de 1 a 100, el yield rendirá todo el tiempo. Si está dentro del rango, entonces llamará a la función de Yield aleatoriamente, según la probabilidad que le des.

Usted dice que no quiere un preprocesador, pero lo hace mucho más fácil.

  #!/usr/bin/perl chomp(my $n =); open (my $f, '<', $n); while (my $l = <$f>) { print $l; if ($l =~ /^[\s][^\.]/) { $r=rand(); if ( int($r*5) == 1 ) { print "\tcall Yield\n"; } } } 

Esta secuencia de comandos de Perl (mi primera vez) leerá un nombre de archivo de stdin e insertará una llamada aleatoriamente en el ensamblado generado por gcc -S que luego se puede comstackr fácilmente. Puede que no funcione como está para su comstackdor / arco, pero las expresiones regulares pueden hacer casi cualquier cosa.

Una buena adición sería agregar un rendimiento siempre antes de las instrucciones de salto para su procesador. Esto te ahorra la aspersión. Finalmente, antes de los saltos, podrías estar usando una función de envoltorio que llama a random ().