This is the mail archive of the cygwin@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RE: Need help with some missing functions


Hi Sergey,
I have sorted out many problems thanks to your help.

I have one more question that I hope you can answer.
I have attached a file called arch.c and I need to choose between
one of the many options for lwpInitContext.  It seems they are architecture
dependent.

Which would you choose to work with the gnu-win32 tools?
thank you
Mark

 
/*
 * arch.c
 *
 * architecture-dependent process context code
 *
 */

#ifndef AIX32

#include "lwp.h"

#include "lwpint.h"

#if defined(hpc)

static struct lwpProc *tempcontext;
struct lwpProc *initcontext=NULL;
int startpoint;

startcontext()
{
	int space[10000];
	int x;

	startpoint = (void *) &x;
        if (!setjmp(initcontext->context)) longjmp(tempcontext->context,1);

        if (!setjmp(tempcontext->context)) longjmp(LwpCurrent->context,1);

	lwpEntryPoint();
}

void lwpInitContext(newp, sp)
        struct lwpProc *newp;
        void            *sp;
{
	struct lwpProc holder;
	int endpoint;

	if (initcontext == NULL) {
		initcontext = (struct lwpProc *) malloc (sizeof(struct lwpProc));
		tempcontext = &holder;
        	if (!setjmp(tempcontext->context)) startcontext();
	}

        tempcontext = newp;
	endpoint = &endpoint;
	if (endpoint < startpoint) {
		if (!setjmp(LwpCurrent->context)) longjmp(initcontext->context,1);
	} else {
		LwpCurrent->size = endpoint - startpoint;
		LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size);
		memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size);
		if (!setjmp(LwpCurrent->context)) longjmp(initcontext->context,1);
		memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size);
	}
}

#elif defined(hpux)

void lwpInitContext(newp, sp)
	volatile struct lwpProc *volatile newp;
	void	*sp;
{
    static jmp_buf *cpp;
    extern struct lwpProc *LwpCurrent;

    if (!lwpSave(LwpCurrent->context)) {
	cpp = (jmp_buf *)&newp->context;
	asm volatile ("ldw	%0, %%sp": : "o" (sp));
	if (!lwpSave(*cpp))
	    lwpRestore(LwpCurrent->context);
	lwpEntryPoint();
    }
}

int lwpSave(jb)
	jmp_buf jb;
{
	/* save stack pointer and return program counter */
	asm ("stw	%sp, 4(%arg0)");
	asm ("stw	%rp, 8(%arg0)");

	/* save "callee save" registers */
	asm ("stw	%r3, 12(%arg0)");
	asm ("stw	%r4, 16(%arg0)");
	asm ("stw	%r5, 20(%arg0)");
	asm ("stw	%r6, 24(%arg0)");
	asm ("stw	%r7, 28(%arg0)");
	asm ("stw	%r8, 32(%arg0)");
	asm ("stw	%r9, 36(%arg0)");
	asm ("stw	%r10, 40(%arg0)");
	asm ("stw	%r11, 44(%arg0)");
	asm ("stw	%r12, 48(%arg0)");
	asm ("stw	%r13, 52(%arg0)");
	asm ("stw	%r14, 56(%arg0)");
	asm ("stw	%r15, 60(%arg0)");
	asm ("stw	%r16, 64(%arg0)");
	asm ("stw	%r17, 68(%arg0)");
	asm ("stw	%r18, 72(%arg0)");

	/* save "callee save" space register */
	asm volatile ("mfsp	%sr3, %r1");
	asm ("stw	%r1, 0(%arg0)");

	/* indicate "true return" from saved() */
	asm ("ldi	0, %ret0");

	asm (".LABEL _comefrom_");
}

void
lwpRestore(jb)
	jmp_buf jb;
{
	/* restore stack pointer and program counter */
	asm volatile ("ldw	4(%arg0), %sp");
	asm volatile ("ldw	8(%arg0), %rp");

	/* restore "callee save" space register */
	asm volatile ("ldw	0(%arg0), %r1");
	asm volatile ("mtsp	%r1, %sr3");

	/* restore "callee save" registers */
	asm volatile ("ldw	12(%arg0), %r3");
	asm volatile ("ldw	16(%arg0), %r4");
	asm volatile ("ldw	20(%arg0), %r5");
	asm volatile ("ldw	24(%arg0), %r6");
	asm volatile ("ldw	28(%arg0), %r7");
	asm volatile ("ldw	32(%arg0), %r8");
	asm volatile ("ldw	36(%arg0), %r9");
	asm volatile ("ldw	40(%arg0), %r10");
	asm volatile ("ldw	44(%arg0), %r11");
	asm volatile ("ldw	48(%arg0), %r12");
	asm volatile ("ldw	52(%arg0), %r13");
	asm volatile ("ldw	56(%arg0), %r14");
	asm volatile ("ldw	60(%arg0), %r15");
	asm volatile ("ldw	64(%arg0), %r16");
	asm volatile ("ldw	68(%arg0), %r17");
	asm volatile ("ldw	72(%arg0), %r18");

	/* warp to saved() to unwind the frame correctly */
	asm volatile ("bl	_comefrom_, %r0");	
	asm volatile ("ldi	1, %ret0");
}

#elif defined(BSD386)
void lwpInitContext(newp, sp)
	struct lwpProc *newp;
	void *sp;
{
	newp->context[2] = (int)sp;
	newp->context[0] = (int)lwpEntryPoint;
}

#elif defined(FBSD)

void lwpInitContext(newp, sp)
        struct lwpProc *newp;
        void *sp;
{
        setjmp (newp->context);
        newp->context->_jb[2] = (int)sp;
        newp->context->_jb[3] = (int)sp;
        newp->context->_jb[0] = (int)lwpEntryPoint;
}

#elif defined(__linux__)

void lwpInitContext(newp, sp)
	struct lwpProc *newp;
	void	*sp;
{
	newp->context->__sp = sp;
	newp->context->__bp = sp;
	newp->context->__pc = (void *)lwpEntryPoint;
}

#elif defined(SUN3)

void lwpInitContext(newp, sp)
	struct lwpProc *newp;
	void	*sp;
{
	newp->context[2] = (int)sp;
	newp->context[3] = (int)lwpEntryPoint;
}

#elif defined(SUN4)

void lwpInitContext(newp, sp)
	struct lwpProc *newp;
	void		*sp;
{
	static jmp_buf *cpp;
	extern struct lwpProc *LwpCurrent;

	bzero(newp->context, sizeof(newp->context));
	newp->context[0] = (int)sp;
	/* preserve cpp for new context */
	cpp = (jmp_buf *)&newp->context;
	if (!_setjmp(LwpCurrent->context)) {
		/* create new context */		
		/* flush registers */
		asm ("ta	0x03");
		/* %o0 <- newp */
		asm ("ld	[%fp+0x44], %o0");
		/* %o1 <- newp->context[0] */
		asm ("ld	[%o0], %o1");
		/* create min frame on new stack */
		asm ("save	%o1,-96, %sp");
		if (!_setjmp(*cpp))
			_longjmp(LwpCurrent->context, 1);
		lwpEntryPoint();
	}
}

#elif defined(__USLC__) && defined(i386)

/* USL/Unixware on an Intel 386/486/... processor.
 * Tested on Unixware v1.1.2, based on SYSV R4.2
 */

/* As per normal empire documentation, there is none.
 *
 * But, what we are attempting to do here is set up a longjump
 * context buffer so that the lwpEntryPoint is called when
 * the thread starts.
 *
 * I.E., what a setjmp/longjmp call set would do.
 *
 * How to figure this out?  Well, without the setjmp code, you
 * need to reverse engineer it by printing out the context buffer
 * and the processor registers, and mapping which ones need
 * to be set.
 *
 * Alternatively, you can single instruction step through the longjmp
 * function, and figure out the offsets that it uses.
 *
 * Using offsets in bytes,
 * context + 0x04 [1] -> esi  (general purpose reg)
 * context + 0x08 [2] -> edi  (general purpose reg)
 * context + 0x0C [3] -> ebp  (general purpose or parameter passing)
 * context + 0x10 [4] -> esp  (stack)
 * context + 0x14 [5] -> jump location for return
 */

void lwpInitContext(newp, sp)
	struct lwpProc *newp;
	void	*sp;
{
	newp->context[4] = (int)sp;
	newp->context[5] = (int)lwpEntryPoint;
}

#elif defined UCONTEXT

/*
 * Alternate aproach using setcontext en getcontext in stead of setjmp and
 * longjump. This should work on any SVr4 machine independant of
 * architecture. Unfortunaltely some changes are still nessesary in lwp.c.
 * Tested on IRIX 5.3
 */ 

void lwpInitContext(newp, spp)
      struct lwpProc *newp;
      stack_t *spp;
{
      getcontext (&(newp->context));
      newp->context.uc_stack.ss_sp = spp->ss_sp;
      newp->context.uc_stack.ss_size = spp->ss_size;
      makecontext (&(newp->context), lwpEntryPoint, 0);
}

#elif defined(ALPHA)

#include <c_asm.h>

void lwpInitContext(newp, sp)
	struct lwpProc *newp;
	void	*sp;
{
	extern long *_gp;

	/* register values obtained from setjmp.h */
	_setjmp(newp->context);
	newp->context[2] = (long)lwpEntryPoint;	/* program counter */
	newp->context[30] = (long)lwpEntryPoint; /* return address */
	newp->context[31] = (long)lwpEntryPoint; /* fake program value (!) */
	newp->context[34] = (long)sp;		/* stack pointer */
}

int lwpSave(jb)
	jmp_buf jb;
{
	return _setjmp(jb);
}

void lwpRestore(jb)
	jmp_buf jb;
{
	/* resume, but get the pv from the jmp_buf */
	asm("ldq	%pv, 248(%a0)");
	asm("stq	%a0, 16(%sp)");
	/* generates a warning, but functions just fine */
	asm("bsr	%ra, __longjump_resume");
}

#endif

#endif

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]