home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / RiscOS / APP / DEVS / LIB / THREAD.ZIP / Thread / ThreadLib / c / VecKludge
Text File  |  1996-12-05  |  4KB  |  137 lines

  1. /* Simtec RiscOS Multithreading Support Code
  2.  * (c) 1996 Neil A Carson / Simtec Electronics
  3.  *
  4.  * Routines to kludge the SharedCLibrary vectors to stop reentrancy problems
  5.  */
  6.  
  7. #pragma no_check_stack
  8.  
  9. #include <stdlib.h>
  10. #include "kernel.h"
  11. #include "thread.h"
  12.  
  13. /* We declare this here because it is not mentioned in any of the standard
  14.  * headers (I don't think)
  15.  */
  16. extern int *SIMTEC_x_stack_overflow;
  17.  
  18. /* This is the semaphore that we use to enforce mutual exclusion
  19.  */
  20. thread_semaphore sem;
  21.  
  22. /* Some general defines
  23.  */
  24. #define PIPELINE 8             /* pc offset due to pipelining */
  25. #define BRANCH 0xEA000000      /* B instruction */
  26. #define BRANCH_MASK 0x00FFFFFF /* Address mask for B instruction */
  27. #define OS_SynchroniseCodeAreas 0x6E /* A SWI number */
  28.  
  29. /* Branch to some assembler at a given address, returning an R0 value
  30.  */
  31. extern int thread_branch_to(int r0, int r1, int r2, int addr);
  32.  
  33. /* My version of malloc()
  34.  */
  35. unsigned real_malloc_addr;
  36. void *unreal_malloc(size_t size)
  37. {
  38.     int stasking, result;
  39.  
  40.     thread_get_context(NULL, (thread_context **) &stasking);
  41.     if (stasking == 0) thread_wait(&sem, NULL);
  42.     result = thread_branch_to(size, 0, 0, real_malloc_addr);
  43.     if (stasking == 0) thread_signal(&sem);
  44.     return (void *) result;
  45. }
  46.  
  47. /* My version of calloc()
  48.  */
  49. unsigned real_calloc_addr;
  50. void *unreal_calloc(size_t nmemb, size_t size)
  51. {
  52.     unsigned stasking, result;
  53.  
  54.     thread_get_context(NULL, (thread_context **) &stasking);
  55.     if (stasking == 0) thread_wait(&sem, NULL);
  56.     result = thread_branch_to(nmemb, size, 0, real_calloc_addr);
  57.     if (stasking == 0) thread_signal(&sem);
  58.     return (void *) result;
  59. }
  60.  
  61. /* My version of realloc()
  62.  */
  63. unsigned real_realloc_addr;
  64. void *unreal_realloc(void *ptr, size_t size)
  65. {
  66.     unsigned stasking, result;
  67.  
  68.     thread_get_context(NULL, (thread_context **) &stasking);
  69.     if (stasking == 0) thread_wait(&sem, NULL);
  70.     thread_branch_to((int) ptr, size, 0, real_realloc_addr);
  71.     if (stasking == 0) thread_signal(&sem);
  72.     return (void *) result;
  73. }
  74.  
  75. /* My version of free()
  76.  */
  77. unsigned real_free_addr;
  78. void unreal_free(size_t size)
  79. {
  80.     unsigned stasking;
  81.  
  82.     thread_get_context(NULL, (thread_context **) &stasking);
  83.     if (stasking == 0) thread_wait(&sem, NULL);
  84.     thread_branch_to(size, 0, 0, real_free_addr); /* Ignore result */
  85.     if (stasking == 0) thread_signal(&sem);
  86. }
  87.  
  88. /* My version of x$stackoverflow
  89.  */
  90. unsigned real_stkovf_addr;
  91. void unreal_stkovf(size_t size)
  92. {
  93.     unsigned stasking;
  94.  
  95.     thread_get_context(NULL, (thread_context **) &stasking);
  96.     if (stasking == 0) thread_wait(&sem, NULL);
  97.     thread_branch_to(size, 0, 0, *SIMTEC_x_stack_overflow);
  98.     if (stasking == 0) thread_signal(&sem);
  99. }
  100.  
  101. /* Claim a vector, storing the old address somewhere.
  102.  */
  103. void thread_claim_vector(unsigned *vec, unsigned *old_addr, unsigned *new_addr)
  104. {
  105.     *old_addr = (int) vec + ((*vec & BRANCH_MASK) << 2) + PIPELINE;
  106.     *vec = ((((int) new_addr - (int) vec - PIPELINE) >> 2) & BRANCH_MASK)
  107.            | BRANCH;
  108. }
  109.  
  110. /* Do the actual kludges. If people are being sensible, there is no real reason
  111.  * why we would want to reverse these kludges, so a function is not supplied to
  112.  * do so.
  113.  */
  114. void thread_kludge(void)
  115. {
  116.     _kernel_swi_regs r;
  117.  
  118.     thread_claim_vector((unsigned *) malloc, (unsigned *) &real_malloc_addr,
  119.                         (unsigned *) unreal_malloc);
  120.     thread_claim_vector((unsigned *) calloc, (unsigned *) &real_calloc_addr,
  121.                         (unsigned *) unreal_calloc);
  122.     thread_claim_vector((unsigned *) realloc, (unsigned *) &real_realloc_addr,
  123.                         (unsigned *) unreal_realloc);
  124.     thread_claim_vector((unsigned *) free, (unsigned *) &real_free_addr,
  125.                         (unsigned *) unreal_free);
  126.     thread_claim_vector((unsigned *) SIMTEC_x_stack_overflow,
  127.                         (unsigned *) &real_stkovf_addr,
  128.                         (unsigned *) unreal_stkovf);
  129.     thread_init_semaphore(&sem, 1);
  130.  
  131.     /* Now, we (may) need to do an OS_SynchroniseCodeAreas SWI here, if we are
  132.      * on a Virtual Harvard machine (ie. StrongARM).
  133.      */
  134.     r.r[0] = 0;
  135.     _kernel_swi(OS_SynchroniseCodeAreas, &r, &r);
  136. }
  137.