This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: aligned attribute and the new operator (pr/15795)


Hi,

Original thread:
http://gcc.gnu.org/ml/gcc/2006-10/msg00166.html

I've finally had time to look at this and try to implement something.

I've attached a preliminary patch for the sake of discussion and to
see if this approach is ok.

Briefly, the idea is to introduce four new special functions,
  void* __align_new   (std::size_t size, std::size_t align);
  void* __align_new_a (std::size_t size, std::size_t align);
  void __align_delete   (void* ptr, std::size_t align);
  void __align_delete_a (void* ptr, std::size_t align);

When a type being operated on with new or delete has alignment greater
than some target defined value the front end searches for one of the
special functions and replaces the call.  The preference for what to
call is, in this order:

  - some class::__align_new
  - some class::operator new
  - if (flag_use_global_align_new) then ::__align_new
  - otherwise ::operator new

Normally, the user will just use the standard new/delete operators and
if the special functions exist, they will be called.  Adding addtional
arguments to __align_new for handling placement new should work too.

One thing I haven't tested much yet is the behaviour when the user
calls the __align_* functions explicitly.  I assume it will work fine.

I went the route of new functions rather than overloading operators
mainly to make the implementation easier.  I didn't want to introduce
templates or attempt to overload the standard operators as were
mentioned in pr/15795.  

I've only just begun testing, so I might find that this implementation
needs too many changes to cover various corner cases, in which case
some other approach might be more appropriate. 

My current testing strategy was to take the existing new/delete test
cases in the testsuite (e.g., new*.C) and create aligned versions of
them.  I think I'll also grep for new in the rest of the testsuite as
well and pick what looks the most useful.  And any other hand written
cases I can come up with.

Some questions. 

  - memalign or posix_memalign?  I'm thinking use posix_memalign for
    GLIBC hosted, and memalign otherwise.

  - Should the special functions behave exactly like the standard
    operators?  e.g., Can't define statically and so on.  Currently my
    goal is for them to be the same, but not sure what I'll encounter
    in testing.

  - Should there be an option to disable this feature completely?
    Possibly adding a preprocessor macro to indicate when it's on.  

I'll actually be on holiday starting Tuesday, and will continue working
on this when I get back next year.  Any initial feedback is appreciated
and I can reply on Monday at least.

Thanks,
Trevor

//#include <cstdlib>
#include <stdio.h>
namespace std {
  typedef long unsigned int size_t;
}
int unaligned_int;
int aligned_int;

struct unaligned
{
  int i;
};

struct aligned
{
  int i;
} __attribute__ ((__aligned__(32)));

struct unaligned_new
{
  void *operator new (std::size_t sz) { return (void *)&unaligned_int; }
  int i;
};

struct aligned_new
{
  void *operator new (std::size_t sz) { return (void *)&unaligned_int; }
  int i;
} __attribute__ ((__aligned__(32)));

struct unaligned_align_new
{
  void *__align_new (std::size_t sz, std::size_t al) { return (void *)&aligned_int; }
  int i;
};

struct aligned_align_new
{
  void *__align_new (std::size_t sz, std::size_t al) { return (void *)&aligned_int; }
  int i;
} __attribute__ ((__aligned__(32)));

struct unaligned_both
{
  void *operator new (std::size_t sz) { return (void *)&unaligned_int; }
  void *__align_new (std::size_t sz, std::size_t al) { return (void *)&aligned_int; }
  int i;
};

struct aligned_both
{
  void *operator new (std::size_t sz) { return (void *)&unaligned_int; }
  void *__align_new (std::size_t sz, std::size_t al) { return (void *)&aligned_int; }
  int i;
} __attribute__ ((__aligned__(32)));

void * f_u() { return new unaligned; }
void * f_a() { return new aligned; }
void * f_un() { return new unaligned_new; }
void * f_an() { return new aligned_new; }
void * f_uan() { return new unaligned_align_new; }
void * f_aan() { return new aligned_align_new; }
void * f_ub() { return new unaligned_both; }
void * f_ab() { return new aligned_both; }

void *operator new (std::size_t sz)
{
  return (void *)&unaligned_int;
}
void *__align_new (std::size_t sz, std::size_t al)
{
  return (void *)&aligned_int;
}

/*extern "C" void abort(void);*/
extern "C" void exit(int);
void
abort(int i)
{
  printf("fail %d\n", i);
}

int
main (void)
{
  if (f_u() != &unaligned_int) abort(__LINE__);
  if (f_a() != &aligned_int) abort(__LINE__);
  if (f_un() != &unaligned_int) abort(__LINE__);
  if (f_an() != &unaligned_int) abort(__LINE__);
  if (f_uan() != &unaligned_int) abort(__LINE__);
  if (f_aan() != &aligned_int) abort(__LINE__);
  if (f_ub() != &unaligned_int) abort(__LINE__);
  if (f_ab() != &aligned_int) abort(__LINE__);

  exit (0);
}

Attachment: alignnew.diff.txt
Description: Text document


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