Proposal: More portable way to support 64bit platforms - Mailing list pgsql-hackers

From Tsutomu Yamada
Subject Proposal: More portable way to support 64bit platforms
Date
Msg-id 62100.1246007244@srapc2360.sra.co.jp
Whole thread Raw
Responses Re: Proposal: More portable way to support 64bit platforms
Re: Proposal: More portable way to support 64bit platforms
List pgsql-hackers
Proposal: More portable way to support 64bit platforms

Short description:

Current PostgreSQL implementation has some portability issues to
support 64bit platforms: pointer calculations using long is not
portable, for example on Windows x64 platform. We propose to use
intptr_t instead of long, which appears in in C99.

Details: intptr_t is defined in <stdint.h>. configure script already
has HAVE_STDINT_H but never uses it. This needs to be enabled.

Please note that Windows/VC++ defines intptr_t in <crtdefs.h>.

Included is a conceptual patch to use intptr_t. Comments are welcome.

Some notes for the patches:

access/common/heaptuple.c:
Casting using (long) is removed. It is no more necessary if we
introduce intptr_t.

include/c.h:
Many Alignment macros which use "long" are rewritten to use intrptr_t.

The patches is against PostgreSQL 8.4beta2. Regression test
passed. Windows x64 is ok even with shared_buffers = 3000MB.

Tested platforms are as follows:

Windows Server 2008 SP1 x64    + Visual Studio 2005
RHEL 4                  x86_64 + gcc 3.4.6
FreeBSD 7.1             i386   + gcc 4.2.1

TODO:
Some problems may occur on older platforms, which do not have
stdint.h. In this case we need to add something like below to
include/port/*.h.

/* LP64, IPL64, ILP32, LP32 */
typedef          long intptr_t;
typedef unsigned long uintptr_t;

/* LLP64 */
typedef          long long intptr_t;
typedef unsigned long long uintptr_t;


Thanks,

--
Tsutomu Yamada // tsutomu@sraoss.co.jp
SRA OSS, Inc. Japan

diff -cwbr postgresql-8.4beta2-orig/src/backend/access/common/heaptuple.c
postgresql-8.4beta2-winx64/src/backend/access/common/heaptuple.c
*** postgresql-8.4beta2-orig/src/backend/access/common/heaptuple.c    2009-03-30 13:08:43.000000000 +0900
--- postgresql-8.4beta2-winx64/src/backend/access/common/heaptuple.c    2009-06-19 16:26:01.000000000 +0900
***************
*** 192,198 ****
          if (att[i]->attbyval)
          {
              /* pass-by-value */
!             data = (char *) att_align_nominal((long) data, att[i]->attalign);
              store_att_byval(data, values[i], att[i]->attlen);
              data_length = att[i]->attlen;
          }
--- 192,198 ----
          if (att[i]->attbyval)
          {
              /* pass-by-value */
!              data = (char *) att_align_nominal(data, att[i]->attalign);
              store_att_byval(data, values[i], att[i]->attlen);
              data_length = att[i]->attlen;
          }
***************
*** 226,232 ****
              else
              {
                  /* full 4-byte header varlena */
!                 data = (char *) att_align_nominal((long) data,
                                                    att[i]->attalign);
                  data_length = VARSIZE(val);
                  memcpy(data, val, data_length);
--- 226,232 ----
              else
              {
                  /* full 4-byte header varlena */
!                 data = (char *) att_align_nominal(data,
                                                    att[i]->attalign);
                  data_length = VARSIZE(val);
                  memcpy(data, val, data_length);
***************
*** 243,249 ****
          else
          {
              /* fixed-length pass-by-reference */
!             data = (char *) att_align_nominal((long) data, att[i]->attalign);
              Assert(att[i]->attlen > 0);
              data_length = att[i]->attlen;
              memcpy(data, DatumGetPointer(values[i]), data_length);
--- 243,249 ----
          else
          {
              /* fixed-length pass-by-reference */
!             data = (char *) att_align_nominal(data, att[i]->attalign);
              Assert(att[i]->attlen > 0);
              data_length = att[i]->attlen;
              memcpy(data, DatumGetPointer(values[i]), data_length);
diff -cwbr postgresql-8.4beta2-orig/src/backend/access/hash/hashfunc.c
postgresql-8.4beta2-winx64/src/backend/access/hash/hashfunc.c
*** postgresql-8.4beta2-orig/src/backend/access/hash/hashfunc.c    2009-02-10 06:18:28.000000000 +0900
--- postgresql-8.4beta2-winx64/src/backend/access/hash/hashfunc.c    2009-06-18 22:37:46.000000000 +0900
***************
*** 319,325 ****
      a = b = c = 0x9e3779b9 + len + 3923095;

      /* If the source pointer is word-aligned, we use word-wide fetches */
!     if (((long) k & UINT32_ALIGN_MASK) == 0)
      {
          /* Code path for aligned source data */
          register const uint32 *ka = (const uint32 *) k;
--- 319,325 ----
      a = b = c = 0x9e3779b9 + len + 3923095;

      /* If the source pointer is word-aligned, we use word-wide fetches */
!     if (((intptr_t) k & UINT32_ALIGN_MASK) == 0)
      {
          /* Code path for aligned source data */
          register const uint32 *ka = (const uint32 *) k;
diff -cwbr postgresql-8.4beta2-orig/src/include/access/tupmacs.h
postgresql-8.4beta2-winx64/src/include/access/tupmacs.h
*** postgresql-8.4beta2-orig/src/include/access/tupmacs.h    2009-01-02 02:23:56.000000000 +0900
--- postgresql-8.4beta2-winx64/src/include/access/tupmacs.h    2009-06-19 16:20:02.000000000 +0900
***************
*** 142,148 ****
  #define att_align_nominal(cur_offset, attalign) \
  ( \
      ((attalign) == 'i') ? INTALIGN(cur_offset) : \
!      (((attalign) == 'c') ? (long) (cur_offset) : \
        (((attalign) == 'd') ? DOUBLEALIGN(cur_offset) : \
         ( \
              AssertMacro((attalign) == 's'), \
--- 142,148 ----
  #define att_align_nominal(cur_offset, attalign) \
  ( \
      ((attalign) == 'i') ? INTALIGN(cur_offset) : \
!     (((attalign) == 'c') ? (intptr_t) (cur_offset) : \
        (((attalign) == 'd') ? DOUBLEALIGN(cur_offset) : \
         ( \
              AssertMacro((attalign) == 's'), \
diff -cwbr postgresql-8.4beta2-orig/src/include/c.h postgresql-8.4beta2-winx64/src/include/c.h
*** postgresql-8.4beta2-orig/src/include/c.h    2009-03-27 07:26:07.000000000 +0900
--- postgresql-8.4beta2-winx64/src/include/c.h    2009-06-19 15:43:35.000000000 +0900
***************
*** 82,87 ****
--- 82,91 ----
  #include <SupportDefs.h>
  #endif

+ #ifdef HAVE_STDINT_H
+ #include <stdint.h>
+ #endif
+
  #if defined(WIN32) || defined(__CYGWIN__)
  /* We have to redefine some system functions after they are included above. */
  #include "pg_config_os.h"
***************
*** 492,498 ****
   *        True iff pointer is properly aligned to point to the given type.
   */
  #define PointerIsAligned(pointer, type) \
!         (((long)(pointer) % (sizeof (type))) == 0)

  #define OidIsValid(objectId)  ((bool) ((objectId) != InvalidOid))

--- 496,502 ----
   *        True iff pointer is properly aligned to point to the given type.
   */
  #define PointerIsAligned(pointer, type) \
!         (((intptr_t)(pointer) % (sizeof (type))) == 0)

  #define OidIsValid(objectId)  ((bool) ((objectId) != InvalidOid))

***************
*** 538,544 ****
   */

  #define TYPEALIGN(ALIGNVAL,LEN)  \
!     (((long) (LEN) + ((ALIGNVAL) - 1)) & ~((long) ((ALIGNVAL) - 1)))

  #define SHORTALIGN(LEN)            TYPEALIGN(ALIGNOF_SHORT, (LEN))
  #define INTALIGN(LEN)            TYPEALIGN(ALIGNOF_INT, (LEN))
--- 542,548 ----
   */

  #define TYPEALIGN(ALIGNVAL,LEN)  \
!     (((intptr_t) (LEN) + ((ALIGNVAL) - 1)) & ~((intptr_t) ((ALIGNVAL) - 1)))

  #define SHORTALIGN(LEN)            TYPEALIGN(ALIGNOF_SHORT, (LEN))
  #define INTALIGN(LEN)            TYPEALIGN(ALIGNOF_INT, (LEN))
***************
*** 549,555 ****
  #define BUFFERALIGN(LEN)        TYPEALIGN(ALIGNOF_BUFFER, (LEN))

  #define TYPEALIGN_DOWN(ALIGNVAL,LEN)  \
!     (((long) (LEN)) & ~((long) ((ALIGNVAL) - 1)))

  #define SHORTALIGN_DOWN(LEN)    TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN))
  #define INTALIGN_DOWN(LEN)        TYPEALIGN_DOWN(ALIGNOF_INT, (LEN))
--- 553,559 ----
  #define BUFFERALIGN(LEN)        TYPEALIGN(ALIGNOF_BUFFER, (LEN))

  #define TYPEALIGN_DOWN(ALIGNVAL,LEN)  \
!     (((intptr_t) (LEN)) & ~((intptr_t) ((ALIGNVAL) - 1)))

  #define SHORTALIGN_DOWN(LEN)    TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN))
  #define INTALIGN_DOWN(LEN)        TYPEALIGN_DOWN(ALIGNOF_INT, (LEN))
***************
*** 630,636 ****
          int        _val = (val); \
          Size    _len = (len); \
  \
!         if ((((long) _vstart) & LONG_ALIGN_MASK) == 0 && \
              (_len & LONG_ALIGN_MASK) == 0 && \
              _val == 0 && \
              _len <= MEMSET_LOOP_LIMIT && \
--- 634,640 ----
          int        _val = (val); \
          Size    _len = (len); \
  \
!         if ((((intptr_t) _vstart) & LONG_ALIGN_MASK) == 0 && \
              (_len & LONG_ALIGN_MASK) == 0 && \
              _val == 0 && \
              _len <= MEMSET_LOOP_LIMIT && \
diff -cwbr postgresql-8.4beta2-orig/src/include/pg_config.h.win32
postgresql-8.4beta2-winx64/src/include/pg_config.h.win32
*** postgresql-8.4beta2-orig/src/include/pg_config.h.win32    2009-05-15 11:18:27.000000000 +0900
--- postgresql-8.4beta2-winx64/src/include/pg_config.h.win32    2009-06-18 19:38:25.000000000 +0900
***************
*** 350,356 ****
  /* #undef HAVE_SRANDOM */

  /* Define to 1 if you have the <stdint.h> header file. */
! #define HAVE_STDINT_H 1

  /* Define to 1 if you have the <stdlib.h> header file. */
  #define HAVE_STDLIB_H 1
--- 350,356 ----
  /* #undef HAVE_SRANDOM */

  /* Define to 1 if you have the <stdint.h> header file. */
! /* #undef HAVE_STDINT_H */

  /* Define to 1 if you have the <stdlib.h> header file. */
  #define HAVE_STDLIB_H 1
diff -cwbr postgresql-8.4beta2-orig/src/interfaces/ecpg/ecpglib/data.c
postgresql-8.4beta2-winx64/src/interfaces/ecpg/ecpglib/data.c
*** postgresql-8.4beta2-orig/src/interfaces/ecpg/ecpglib/data.c    2009-01-15 20:52:55.000000000 +0900
--- postgresql-8.4beta2-winx64/src/interfaces/ecpg/ecpglib/data.c    2009-06-18 19:29:20.000000000 +0900
***************
*** 153,163 ****
              if (pval)
              {
                  if (varcharsize == 0 || varcharsize * offset >= size)
!                     memcpy((char *) ((long) var + offset * act_tuple),
                             pval, size);
                  else
                  {
!                     memcpy((char *) ((long) var + offset * act_tuple),
                             pval, varcharsize * offset);

                      if (varcharsize * offset < size)
--- 153,163 ----
              if (pval)
              {
                  if (varcharsize == 0 || varcharsize * offset >= size)
!                     memcpy((char *) ((intptr_t) var + offset * act_tuple),
                             pval, size);
                  else
                  {
!                     memcpy((char *) ((intptr_t) var + offset * act_tuple),
                             pval, varcharsize * offset);

                      if (varcharsize * offset < size)
***************
*** 392,401 ****
                      if (pval)
                      {
                          if (varcharsize == 0 || varcharsize > size)
!                             strncpy((char *) ((long) var + offset * act_tuple), pval, size + 1);
                          else
                          {
!                             strncpy((char *) ((long) var + offset * act_tuple), pval, varcharsize);

                              if (varcharsize < size)
                              {
--- 392,401 ----
                      if (pval)
                      {
                          if (varcharsize == 0 || varcharsize > size)
!                             strncpy((char *) ((intptr_t) var + offset * act_tuple), pval, size + 1);
                          else
                          {
!                             strncpy((char *) ((intptr_t) var + offset * act_tuple), pval, varcharsize);

                              if (varcharsize < size)
                              {
***************
*** 434,440 ****
                      if (pval)
                      {
                          struct ECPGgeneric_varchar *variable =
!                         (struct ECPGgeneric_varchar *) ((long) var + offset * act_tuple);

                          variable->len = size;
                          if (varcharsize == 0)
--- 434,440 ----
                      if (pval)
                      {
                          struct ECPGgeneric_varchar *variable =
!                         (struct ECPGgeneric_varchar *) ((intptr_t) var + offset * act_tuple);

                          variable->len = size;
                          if (varcharsize == 0)
diff -cwbr postgresql-8.4beta2-orig/src/pl/plperl/plperl.c postgresql-8.4beta2-winx64/src/pl/plperl/plperl.c
*** postgresql-8.4beta2-orig/src/pl/plperl/plperl.c    2009-02-20 19:39:19.000000000 +0900
--- postgresql-8.4beta2-winx64/src/pl/plperl/plperl.c    2009-06-18 19:25:06.000000000 +0900
***************
*** 2192,2198 ****
       ************************************************************/
      qdesc = (plperl_query_desc *) malloc(sizeof(plperl_query_desc));
      MemSet(qdesc, 0, sizeof(plperl_query_desc));
!     snprintf(qdesc->qname, sizeof(qdesc->qname), "%lx", (long) qdesc);
      qdesc->nargs = argc;
      qdesc->argtypes = (Oid *) malloc(argc * sizeof(Oid));
      qdesc->arginfuncs = (FmgrInfo *) malloc(argc * sizeof(FmgrInfo));
--- 2192,2198 ----
       ************************************************************/
      qdesc = (plperl_query_desc *) malloc(sizeof(plperl_query_desc));
      MemSet(qdesc, 0, sizeof(plperl_query_desc));
!     snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
      qdesc->nargs = argc;
      qdesc->argtypes = (Oid *) malloc(argc * sizeof(Oid));
      qdesc->arginfuncs = (FmgrInfo *) malloc(argc * sizeof(FmgrInfo));
diff -cwbr postgresql-8.4beta2-orig/src/port/open.c postgresql-8.4beta2-winx64/src/port/open.c
*** postgresql-8.4beta2-orig/src/port/open.c    2009-01-02 02:24:04.000000000 +0900
--- postgresql-8.4beta2-winx64/src/port/open.c    2009-06-18 19:22:08.000000000 +0900
***************
*** 123,129 ****
      }

      /* _open_osfhandle will, on error, set errno accordingly */
!     if ((fd = _open_osfhandle((long) h, fileFlags & O_APPEND)) < 0)
          CloseHandle(h);            /* will not affect errno */
      else if (fileFlags & (O_TEXT | O_BINARY) &&
               _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
--- 123,129 ----
      }

      /* _open_osfhandle will, on error, set errno accordingly */
!     if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
          CloseHandle(h);            /* will not affect errno */
      else if (fileFlags & (O_TEXT | O_BINARY) &&
               _setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)

pgsql-hackers by date:

Previous
From: Scara Maccai
Date:
Subject: Query progress indication - an implementation
Next
From: Stephen Frost
Date:
Subject: Re: [PATCH] backend: compare word-at-a-time in bcTruelen