m3core/src/thread/PTHREAD/ThreadApple.c


/* Copyright (C) 2005, Purdue Research Foundation                  */
/* All rights reserved.                                            */
/* See the file COPYRIGHT-PURDUE for a full description.           */

#ifndef __APPLE__

#if __GNUC__ >= 4
#pragma GCC visibility push(hidden)
#endif

/* avoid empty file */

void ThreadApple__Dummy(void)
{
}

#else

/* Older and newer headers default __DARWIN_UNIX03 to 1,
 * but only newer headers rename the symbols we use
 * under it, so we have to change to to 0.
 */
#ifndef __DARWIN_UNIX03
#define __DARWIN_UNIX03 0
#endif

#include "m3core.h"
#include <sys/ucontext.h>

#include <mach/mach.h>
#include <mach/thread_act.h>
#if defined(__ppc__) || defined(__ppc64__)
#include <architecture/ppc/cframe.h>
#endif

#if __GNUC__ >= 4
#pragma GCC visibility push(hidden)
#endif

#ifdef __cplusplus
extern "C" {
#endif

int
ThreadPThread__SuspendThread (m3_pthread_t mt)
{
  mach_port_t mach_thread = pthread_mach_thread_np(PTHREAD_FROM_M3(mt));
  if (thread_suspend(mach_thread) != KERN_SUCCESS)
    return 0;
  if (thread_abort_safely(mach_thread) != KERN_SUCCESS)
  {
    kern_return_t status = thread_resume(mach_thread);
    if (status != KERN_SUCCESS)
    {
      fprintf(stderr, "thread_resume returned %d instead of %d\n",
              (int)status, (int)KERN_SUCCESS);
      abort();
    }
    return 0;
  }
  return 1;
}

int
ThreadPThread__RestartThread (m3_pthread_t mt)
{
  mach_port_t mach_thread = pthread_mach_thread_np(PTHREAD_FROM_M3(mt));
  return thread_resume(mach_thread) == KERN_SUCCESS;
}

#if __DARWIN_UNIX03
#define M3__(x) __##x
#else
#define M3__(x) x
#endif

#ifdef __ppc__
typedef ppc_thread_state_t m3_thread_state_t;
#define M3_THREAD_STATE       PPC_THREAD_STATE
#define M3_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT
#define M3_STACK_REGISTER M3__(r1)
#define M3_STACK_ADJUST C_RED_ZONE
#endif /* ppc */

#ifdef __ppc64__
typedef ppc_thread_state64_t m3_thread_state_t;
#define M3_THREAD_STATE       PPC_THREAD_STATE64
#define M3_THREAD_STATE_COUNT PPC_THREAD_STATE64_COUNT
#define M3_STACK_REGISTER M3__(r1)
#define M3_STACK_ADJUST C_RED_ZONE
#endif /* ppc64 */

#ifdef __i386__
typedef i386_thread_state_t m3_thread_state_t;
#define M3_THREAD_STATE       i386_THREAD_STATE
#define M3_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT
#define M3_STACK_REGISTER M3__(esp)
#define M3_STACK_ADJUST 0
#endif /* i386 */

#ifdef __x86_64__
typedef x86_thread_state64_t m3_thread_state_t;
#define M3_THREAD_STATE       x86_THREAD_STATE64
#define M3_THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
#define M3_STACK_REGISTER M3__(rsp)
#define M3_STACK_ADJUST 128
#endif /* amd64 */

#ifdef __arm__
#if __DARWIN_UNIX03
typedef struct __darwin_arm_thread_state m3_thread_state_t;
#else
typedef struct arm_thread_state m3_thread_state_t;
#endif
#define M3_THREAD_STATE       ARM_THREAD_STATE
#define M3_THREAD_STATE_COUNT ARM_THREAD_STATE_COUNT
/*define M3_STACK_REGISTER r13*/
#define M3_STACK_REGISTER sp
#define M3_STACK_ADJUST 0
#endif /* arm */

void
ThreadPThread__ProcessStopped (m3_pthread_t mt, void *bottom, void *context,
                               void (*p)(void *start, void *limit))
{
  void *sp;
  m3_thread_state_t state;
  kern_return_t status;
  mach_port_t mach_thread = pthread_mach_thread_np(PTHREAD_FROM_M3(mt));
  mach_msg_type_number_t thread_state_count = M3_THREAD_STATE_COUNT;
  status = thread_get_state(mach_thread, M3_THREAD_STATE,
                            (thread_state_t)&state, &thread_state_count);
  if (status != KERN_SUCCESS)
  {
    fprintf(stderr, "thread_get_state returned %d instead of %d\n",
            (int)status, (int)KERN_SUCCESS);
    abort();
  }
  if (thread_state_count != M3_THREAD_STATE_COUNT)
  {
    fprintf(stderr,
            "thread_get_state returned thread_state_count %d instead of %d\n",
            (int)thread_state_count, (int)M3_THREAD_STATE_COUNT);
    abort();
  }
  sp = (void *)(state.M3_STACK_REGISTER - M3_STACK_ADJUST);
  /* process the stack */
#if 0
  assert(stack_grows_down); /* See ThreadPThreadC.c */
#endif
  assert(context == 0);
  p(sp, bottom);
  /* process the registers */
  p(&state, &state + 1);
}

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif