Esempio n. 1
0
WRAPPER(int , munmap, void *start, size_t length)
{
  DECLARE(int, munmap, void *, size_t);
  int result;
  BEGIN_PROTECT (munmap, start, length);

  result = CALL_REAL (munmap, start, length);

  /*
  VERBOSE_TRACE ("munmap (%08lx, %08lx, ...) => %08lx\n",
		 (uintptr_t) start, (uintptr_t) length,
		 (uintptr_t) result);
  */

  if (result == 0)
    {
      /* Unregister each page as a heap object.  */
      size_t ps = getpagesize ();
      uintptr_t base = (uintptr_t) start & (~ (ps - 1)); /* page align */
      uintptr_t offset;

      for (offset=0; offset<length; offset+=ps)
	__mf_unregister ((void *) CLAMPADD (base, offset), ps, __MF_TYPE_HEAP_I);
    }
  return result;
}
Esempio n. 2
0
int main ()
{
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
#ifdef HAVE_MMAP
  volatile unsigned char *p;
  unsigned num = getpagesize ();
  unsigned i;
  int rc;

  /* Get a bit of usable address space.  We really want an 2**N+1-sized object,
     so the low/high addresses wrap when hashed into the lookup cache.  So we
     will manually unregister the entire mmap, then re-register a slice.  */
  p = mmap (NULL, num, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  if (p == NULL)
    return 1;
  /* Now unregister it, as if munmap was called.  But don't actually munmap, so
     we can write into the memory.  */
  __mf_unregister ((void *) p, num, __MF_TYPE_HEAP_I);

  /* Now register it under a slightly inflated, 2**N+1 size.  */
  __mf_register ((void *) p, num+1, __MF_TYPE_HEAP_I, "fake mmap registration");

  /* Traverse array to ensure that entire lookup cache is made to point at it.  */
  for (i=0; i<num; i++)
    p[i] = 0;

  /* Unregister it.  This should clear the entire lookup cache, even though
     hash(low) == hash (high)  (and probably == 0) */
  __mf_unregister ((void *) p, num+1, __MF_TYPE_HEAP_I);

  /* Now touch the middle portion of the ex-array.  If the lookup cache was
     well and truly cleaned, then this access should trap.  */
  p[num/2] = 1;

  return 0;
#else
  return 1;
#endif
}
Esempio n. 3
0
static void 
__mf_pthread_cleanup (void *arg)
{
  struct pthread_info *pi = arg;

  /* XXX: This unregistration is not safe on platforms where distinct
     threads share errno (or at least its virtual address).  */
  if (pi->thread_errno != NULL)
    __mf_unregister (pi->thread_errno, sizeof (int), __MF_TYPE_GUESS);

  /* XXX: Only detached threads should designate themselves as dead
     here.  Non-detached threads are marked dead after their
     personalized pthread_join() call.  */
  pi->state = reentrant;
  pi->dead_p = 1;

  VERBOSE_TRACE ("thread pi %p exiting\n", pi);
}
Esempio n. 4
0
/* This wrapper is a little different, as it's called indirectly from
   __mf_fini also to clean up pending allocations.  */
void *
__mf_wrap_alloca_indirect (size_t c)
{
  DECLARE (void *, malloc, size_t);
  DECLARE (void, free, void *);

  /* This struct, a linked list, tracks alloca'd objects.  The newest
     object is at the head of the list.  If we detect that we've
     popped a few levels of stack, then the listed objects are freed
     as needed.  NB: The tracking struct is allocated with
     real_malloc; the user data with wrap_malloc.
  */
  struct alloca_tracking { void *ptr; void *stack; struct alloca_tracking* next; };
  static struct alloca_tracking *alloca_history = NULL;

  void *stack = __builtin_frame_address (0);
  void *result;
  struct alloca_tracking *track;

  TRACE ("%s\n", __PRETTY_FUNCTION__);
  VERBOSE_TRACE ("alloca stack level %p\n", (void *) stack);

  /* XXX: thread locking! */

  /* Free any previously alloca'd blocks that belong to deeper-nested functions,
     which must therefore have exited by now.  */

#define DEEPER_THAN < /* XXX: for x86; steal find_stack_direction() from libiberty/alloca.c */

  while (alloca_history &&
	 ((uintptr_t) alloca_history->stack DEEPER_THAN (uintptr_t) stack))
    {
      struct alloca_tracking *next = alloca_history->next;
      __mf_unregister (alloca_history->ptr, 0, __MF_TYPE_HEAP);
      BEGIN_MALLOC_PROTECT ();
      CALL_REAL (free, alloca_history->ptr);
      CALL_REAL (free, alloca_history);
      END_MALLOC_PROTECT ();
      alloca_history = next;
    }

  /* Allocate new block.  */
  result = NULL;
  if (LIKELY (c > 0)) /* alloca(0) causes no allocation.  */
    {
      BEGIN_MALLOC_PROTECT ();
      track = (struct alloca_tracking *) CALL_REAL (malloc,
						    sizeof (struct alloca_tracking));
      END_MALLOC_PROTECT ();
      if (LIKELY (track != NULL))
	{
	  BEGIN_MALLOC_PROTECT ();
	  result = CALL_REAL (malloc, c);
	  END_MALLOC_PROTECT ();
	  if (UNLIKELY (result == NULL))
	    {
	      BEGIN_MALLOC_PROTECT ();
	      CALL_REAL (free, track);
	      END_MALLOC_PROTECT ();
	      /* Too bad.  XXX: What about errno?  */
	    }
	  else
	    {
	      __mf_register (result, c, __MF_TYPE_HEAP, "alloca region");
	      track->ptr = result;
	      track->stack = stack;
	      track->next = alloca_history;
	      alloca_history = track;
	    }
	}
    }

  return result;
}
Esempio n. 5
0
WRAPPER(void, free, void *buf)
{
  /* Use a circular queue to delay some number (__mf_opts.free_queue_length) of free()s.  */
  static void *free_queue [__MF_FREEQ_MAX];
  static unsigned free_ptr = 0;
  static int freeq_initialized = 0;
  DECLARE(void, free, void *);

  if (UNLIKELY(buf == NULL))
    return;

  BEGIN_PROTECT (free, buf);

#if PIC
  /* Check whether the given buffer might have come from a
     __mf_0fn_malloc/calloc call that for whatever reason was not
     redirected back to __mf_0fn_free.  If so, we just ignore the
     call. */
  if (UNLIKELY((uintptr_t) buf >= (uintptr_t) __mf_0fn_bufs &&
               (uintptr_t) buf < ((uintptr_t) __mf_0fn_bufs + sizeof(__mf_0fn_bufs))))
  {
    VERBOSE_TRACE ("skipping free of boot (0fn) alloc buffer %p\n", buf);
    return;
  }
#endif

  LOCKTH ();
  if (UNLIKELY(!freeq_initialized))
    {
      memset (free_queue, 0,
		     __MF_FREEQ_MAX * sizeof (void *));
      freeq_initialized = 1;
    }
  UNLOCKTH ();

  __mf_unregister (buf, 0, __MF_TYPE_HEAP_I);
  /* NB: underlying region may have been __MF_TYPE_HEAP. */

  if (UNLIKELY(__mf_opts.free_queue_length > 0))
    {
      char *freeme = NULL;
      LOCKTH ();
      if (free_queue [free_ptr] != NULL)
	{
	  freeme = free_queue [free_ptr];
	  freeme -= __mf_opts.crumple_zone;
	}
      free_queue [free_ptr] = buf;
      free_ptr = (free_ptr == (__mf_opts.free_queue_length-1) ? 0 : free_ptr + 1);
      UNLOCKTH ();
      if (freeme)
	{
	  if (__mf_opts.trace_mf_calls)
	    {
	      VERBOSE_TRACE ("freeing deferred pointer %p (crumple %u)\n",
			     (void *) freeme,
			     __mf_opts.crumple_zone);
	    }
	  BEGIN_MALLOC_PROTECT ();
	  CALL_REAL (free, freeme);
	  END_MALLOC_PROTECT ();
	}
    }
  else
    {
      /* back pointer up a bit to the beginning of crumple zone */
      char *base = (char *)buf;
      base -= __mf_opts.crumple_zone;
      if (__mf_opts.trace_mf_calls)
	{
	  VERBOSE_TRACE ("freeing pointer %p = %p - %u\n",
			 (void *) base,
			 (void *) buf,
			 __mf_opts.crumple_zone);
	}
      BEGIN_MALLOC_PROTECT ();
      CALL_REAL (free, base);
      END_MALLOC_PROTECT ();
    }
}
Esempio n. 6
0
void HostScreen_setWindowSize(int width, int height, int bpp)
{
	int screenwidth, screenheight, maxw, maxh;
	int scalex, scaley, sbarheight;

	if (bpp == 24)
		bpp = 32;

	/* constrain size request to user's desktop size */
	Resolution_GetDesktopSize(&maxw, &maxh);
	scalex = scaley = 1;
	while (width > maxw*scalex) {
		scalex *= 2;
	}
	while (height > maxh*scalex) {
		scalex *= 2;
	}
	if (scalex * scaley > 1) {
		fprintf(stderr, "WARNING: too large screen size %dx%d -> divided by %dx%d!\n",
			width, height, scalex, scaley);
		width /= scalex;
		height /= scaley;
	}

	Resolution_GetLimits(&maxw, &maxh, &bpp);
	nScreenZoomX = nScreenZoomY = 1;
	
	if (ConfigureParams.Screen.bAspectCorrect) {
		/* Falcon (and TT) pixel scaling factors seem to 2^x
		 * (quarter/half pixel, interlace/double line), so
		 * do aspect correction as 2's exponent.
		 */
		while (nScreenZoomX*width < height &&
		       2*nScreenZoomX*width < maxw) {
			nScreenZoomX *= 2;
		}
		while (2*nScreenZoomY*height < width &&
		       2*nScreenZoomY*height < maxh) {
			nScreenZoomY *= 2;
		}
		if (nScreenZoomX*nScreenZoomY > 2) {
			fprintf(stderr, "WARNING: strange screen size %dx%d -> aspect corrected by %dx%d!\n",
				width, height, nScreenZoomX, nScreenZoomY);
		}
	}

	/* then select scale as close to target size as possible
	 * without having larger size than it
	 */
	scalex = maxw/(nScreenZoomX*width);
	scaley = maxh/(nScreenZoomY*height);
	if (scalex > 1 && scaley > 1) {
		/* keep aspect ratio */
		if (scalex < scaley) {
			nScreenZoomX *= scalex;
			nScreenZoomY *= scalex;
		} else {
			nScreenZoomX *= scaley;
			nScreenZoomY *= scaley;
		}
	}

	hs_width_req = width;
	hs_height_req = height;
	width *= nScreenZoomX;
	height *= nScreenZoomY;

	/* get statusbar size for this screen size */
	sbarheight = Statusbar_GetHeightForSize(width, height);
	screenheight = height + sbarheight;
	screenwidth = width;

	/* get resolution corresponding to these */
	Resolution_Search(&screenwidth, &screenheight, &bpp);
	/* re-calculate statusbar height for this resolution */
	sbarheight = Statusbar_SetHeight(screenwidth, screenheight-sbarheight);

	hs_bpp = bpp;
	/* videl.c might scale things differently in fullscreen than
	 * in windowed mode because this uses screensize instead of using
	 * the aspect scaled sizes directly, but it works better this way.
	 */
	hs_width = screenwidth;
	hs_height = screenheight - sbarheight;

	if (sdlscrn && (!bpp || sdlscrn->format->BitsPerPixel == bpp) &&
	    sdlscrn->w == (signed)screenwidth && sdlscrn->h == (signed)screenheight &&
	    (sdlscrn->flags&SDL_FULLSCREEN) == (sdl_videoparams&SDL_FULLSCREEN))
	{
		/* same host screen size despite Atari resolution change,
		 * -> no time consuming host video mode change needed
		 */
		if (screenwidth > width || screenheight > height+sbarheight) {
			/* Atari screen smaller than host -> clear screen */
			SDL_Rect rect;
			rect.x = 0;
			rect.y = 0;
			rect.w = sdlscrn->w;
			rect.h = sdlscrn->h - sbarheight;
			SDL_FillRect(sdlscrn, &rect, SDL_MapRGB(sdlscrn->format, 0, 0, 0));
			/* re-calculate variables in case height + statusbar height
			 * don't anymore match SDL surface size (there's an assert
			 * for that)
			 */
			Statusbar_Init(sdlscrn);
		}
		// check in case switched from VDI to Hostscreen
		doUpdate = ( sdlscrn->flags & SDL_HWSURFACE ) == 0;
		return;
	}

	if (bInFullScreen) {
		/* un-embed the Hatari WM window for fullscreen */
		Control_ReparentWindow(screenwidth, screenheight, bInFullScreen);

		sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN;
	} else {
		sdl_videoparams = SDL_SWSURFACE|SDL_HWPALETTE;
	}
#ifdef _MUDFLAP
	if (sdlscrn) {
		__mf_unregister(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS);
	}
#endif
	sdlscrn = SDL_SetVideoMode(screenwidth, screenheight, bpp, sdl_videoparams);
#ifdef _MUDFLAP
	__mf_register(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS, "SDL pixels");
#endif
	if (!bInFullScreen) {
		/* re-embed the new Hatari SDL window */
		Control_ReparentWindow(screenwidth, screenheight, bInFullScreen);
	}

	// In case surface format changed, update SDL palette & remap the native palette
	HostScreen_updatePalette(256);
	HostScreen_remapPalette();

	// redraw statusbar
	Statusbar_Init(sdlscrn);

	Dprintf(("Surface Pitch = %d, width = %d, height = %d\n", sdlscrn->pitch, sdlscrn->w, sdlscrn->h));
	Dprintf(("Must Lock? %s\n", SDL_MUSTLOCK(sdlscrn) ? "YES" : "NO"));

	// is the SDL_update needed?
	doUpdate = ( sdlscrn->flags & SDL_HWSURFACE ) == 0;

	Dprintf(("Pixel format:bitspp=%d, tmasks r=%04x g=%04x b=%04x"
			", tshifts r=%d g=%d b=%d"
			", tlosses r=%d g=%d b=%d\n",
			sdlscrn->format->BitsPerPixel,
			sdlscrn->format->Rmask, sdlscrn->format->Gmask, sdlscrn->format->Bmask,
			sdlscrn->format->Rshift, sdlscrn->format->Gshift, sdlscrn->format->Bshift,
			sdlscrn->format->Rloss, sdlscrn->format->Gloss, sdlscrn->format->Bloss));

	Main_WarpMouse(sdlscrn->w/2,sdlscrn->h/2);
}
Esempio n. 7
0
/**
 * Initialize SDL screen surface / set resolution.
 */
static void Screen_SetResolution(void)
{
	int Width, Height, nZoom, SBarHeight, BitCount, maxW, maxH;
	bool bDoubleLowRes = false;

	BitCount = 0; /* host native */

	nBorderPixelsTop = nBorderPixelsBottom = 0;
	nBorderPixelsLeft = nBorderPixelsRight = 0;

	nScreenZoomX = 1;
	nScreenZoomY = 1;

	Width = 1120;
	Height = 832;
	nZoom = 1;

	/* Statusbar height for doubled screen size */
	SBarHeight = Statusbar_GetHeightForSize(1120, 832);
	Resolution_GetLimits(&maxW, &maxH, &BitCount);
		
	
	Screen_SetSTScreenOffsets();  
	Height += Statusbar_SetHeight(Width, Height);

	/* Check if we really have to change the video mode: */
	if (!sdlscrn || sdlscrn->w != Width || sdlscrn->h != Height
	    || (BitCount && sdlscrn->format->BitsPerPixel != BitCount))
	{
#ifdef _MUDFLAP
		if (sdlscrn) {
			__mf_unregister(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS);
		}
#endif
		if (bInFullScreen)
		{
			/* unhide the Hatari WM window for fullscreen */
			Control_ReparentWindow(Width, Height, bInFullScreen);
		}
		
		/* Set new video mode */
        SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");

		fprintf(stderr, "SDL screen request: %d x %d @ %d (%s)\n", Width, Height, BitCount, bInFullScreen?"fullscreen":"windowed");
		sdlWindow = SDL_CreateWindow(PROG_NAME,
		                             SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		                             Width, Height, 0);
		sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);
		if (!sdlWindow || !sdlRenderer)
		{
			fprintf(stderr,"Failed to create window or renderer!\n");
			exit(-1);
		}
		SDL_RenderSetLogicalSize(sdlRenderer, Width, Height);
		sdlscrn = SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 32,
						0x00FF0000, 0x0000FF00,
						0x000000FF, 0x00000000);
		sdlTexture = SDL_CreateTexture(sdlRenderer,
						SDL_PIXELFORMAT_RGB888,
						SDL_TEXTUREACCESS_STREAMING,
						Width, Height);
		fprintf(stderr, "SDL screen granted: %d x %d @ %d\n", sdlscrn->w, sdlscrn->h, sdlscrn->format->BitsPerPixel);

		/* Exit if we can not open a screen */
		if (!sdlscrn)
		{
			fprintf(stderr, "Could not set video mode:\n %s\n", SDL_GetError() );
			SDL_Quit();
			exit(-2);
		}
#ifdef _MUDFLAP
		__mf_register(sdlscrn->pixels, sdlscrn->pitch*sdlscrn->h, __MF_TYPE_GUESS, "SDL pixels");
#endif

		if (!bInFullScreen)
		{
			/* re-embed the new Hatari SDL window */
			Control_ReparentWindow(Width, Height, bInFullScreen);
		}
		
		/* Re-init screen palette: */
		if (sdlscrn->format->BitsPerPixel == 8)
			Screen_Handle8BitPalettes();    /* Initialize new 8 bit palette */
		else
			Screen_SetupRGBTable();         /* Create color convertion table */

		Statusbar_Init(sdlscrn);
		
		/* screen area without the statusbar */
		NEXTScreenRect.x = 0;
		NEXTScreenRect.y = 0;
		NEXTScreenRect.w = sdlscrn->w;
		NEXTScreenRect.h = sdlscrn->h - Statusbar_GetHeight();
	}

	/* Set drawing functions */
	Screen_SetDrawFunctions(sdlscrn->format->BitsPerPixel, bDoubleLowRes);

	Screen_SetFullUpdate();           /* Cause full update of screen */
}
Esempio n. 8
0
WRAPPER(void, free, void *buf)
{
  /* Use a circular queue to delay some number (__mf_opts.free_queue_length) of free()s.  */
  static void *free_queue [__MF_FREEQ_MAX];
  static unsigned free_ptr = 0;
  static int freeq_initialized = 0;
  DECLARE(void, free, void *);

  BEGIN_PROTECT (free, buf);

  if (UNLIKELY(buf == NULL))
    return;

  LOCKTH ();
  if (UNLIKELY(!freeq_initialized))
    {
      memset (free_queue, 0,
		     __MF_FREEQ_MAX * sizeof (void *));
      freeq_initialized = 1;
    }
  UNLOCKTH ();

  __mf_unregister (buf, 0, __MF_TYPE_HEAP_I);
  /* NB: underlying region may have been __MF_TYPE_HEAP. */

  if (UNLIKELY(__mf_opts.free_queue_length > 0))
    {
      char *freeme = NULL;
      LOCKTH ();
      if (free_queue [free_ptr] != NULL)
	{
	  freeme = free_queue [free_ptr];
	  freeme -= __mf_opts.crumple_zone;
	}
      free_queue [free_ptr] = buf;
      free_ptr = (free_ptr == (__mf_opts.free_queue_length-1) ? 0 : free_ptr + 1);
      UNLOCKTH ();
      if (freeme)
	{
	  if (__mf_opts.trace_mf_calls)
	    {
	      VERBOSE_TRACE ("freeing deferred pointer %p (crumple %u)\n",
			     (void *) freeme,
			     __mf_opts.crumple_zone);
	    }
	  BEGIN_MALLOC_PROTECT ();
	  CALL_REAL (free, freeme);
	  END_MALLOC_PROTECT ();
	}
    }
  else
    {
      /* back pointer up a bit to the beginning of crumple zone */
      char *base = (char *)buf;
      base -= __mf_opts.crumple_zone;
      if (__mf_opts.trace_mf_calls)
	{
	  VERBOSE_TRACE ("freeing pointer %p = %p - %u\n",
			 (void *) base,
			 (void *) buf,
			 __mf_opts.crumple_zone);
	}
      BEGIN_MALLOC_PROTECT ();
      CALL_REAL (free, base);
      END_MALLOC_PROTECT ();
    }
}