1. 06 Aug, 2015 8 commits
    • bigfile/virtmem: Big Virtmem lock · d53271b9
      At present several threads running can corrupt internal virtmem
      datastructures (e.g. ram->lru_list, fileh->pagemap, etc).
      
      This can happen even if we have zope instances only with 1 worker thread
      - because there are other "system" thread, and python garbage collection
      can trigger at any thread, so if a virtmem object, e.g. VMA or FileH was
      there sitting at GC queue to be collected, their collection, and thus
      e.g. vma_unmap() and fileh_close() will be called from
      different-from-worker thread.
      
      Because of that virtmem just has to be aware of threads not to allow
      internal datastructure corruption.
      
      On the other hand, the idea of introducing userspace virtual memory
      manager turned out to be not so good from performance and complexity
      point of view, and thus the plan is to try to move it back into the
      kernel. This way it does not make sense to do a well-optimised locking
      implementation for userspace version.
      
      So we do just a simple single "protect-all" big lock for virtmem.
      
      Of a particular note is interaction with Python's GIL - any long-lived
      lock has to be taken with GIL released, because else it can deadlock:
      
          t1  t2
      
          G
          V   G
         !G   V
          G
      
      so we introduce helpers to make sure the GIL is not taken, and to retake
      it back if we were holding it initially.
      
      Those helpers (py_gil_ensure_unlocked / py_gil_retake_if_waslocked) are
      symmetrical opposites to what Python provides to make sure the GIL is
      locked (via PyGILState_Ensure / PyGILState_Release).
      
      Otherwise, the patch is more-or-less straightforward application for
      one-big-lock to protect everything idea.
      Kirill Smelkov committed
    • lib/utils: X- versions for pthread_mutex_{lock,unlock} · 78cbf2a0
      Mutex lock/unlock should not fail if mutex was correctly initialized/used.
      Kirill Smelkov committed
    • bigfile: Simple test that we can handle GC from-under sighandler · 786d418d
      And specifically that GC'ed object __del__ calls into virtmem
      (vma_dealloc and fileh_dealloc) again.
      
      NOTE not sure it is a good idea to do GC from under sighandle, but
           currently it happens in practice, because we did not cared to
           protect against it.
      Kirill Smelkov committed
    • bigfile/virtmem: When restoring SIGSEGV, don't change procmask for other signals · d7c33cd7
      We factored out SIGSEGV block/restore from fileh_dirty_writeout() to all
      functions in cb7a7055 (bigfile/virtmem: Block/restore SIGSEGV in
      non-pagefault-handling function). The restoration however just sets
      whole thread sigmask.
      
      It could be possible that between block/restore calls procmask for other
      signals could be changed, and this way - setting procmask directly - we
      will overwrite them.
      
      So be careful, and when restoring SIGSEGV mask, touch mask bit for only
      that signal.
      
      ( we need xsigismember helper to get this done, which is also introduced
        in this patch )
      Kirill Smelkov committed
    • lib/utils: pthread_sigmask() returns error directly, not in errno · 8fa9af7f
      The mistake was there from the beginning - from 3e5e78cd (lib/utils:
      Small C utilities we'll use).
      Kirill Smelkov committed
    • lib/bug: BUGerr(err) - like BUGe() but takes error code explicitly · ec6ecd4e
      We'll need this for function which return error not in errno - e.g.
      pthread_sigmask().
      Kirill Smelkov committed
    • bigfile/virtmem: Block/restore SIGSEGV in non-pagefault-handling function · cb7a7055
      Non on-pagefault code should not access any not-mmapped memory.
      
      Here we just refactor the code we already had to block/restore
      SIGSEGV from fileh_dirty_writeout() and use it in all functions called
      from non-pagefaulting context, as promised.
      
      This way, if there is an error in virtmem implementation which
      incorrectly accesses prepared for BigFile maps memory, we'll just die
      with coredump instead of trying to incorrectly handle the pagefault.
      Kirill Smelkov committed
  2. 27 Jul, 2015 1 commit
    • bigarray: In-place .append() · 1245acc9
      ca064f75 (bigarray: Support resizing in-place) added O(1) in-place
      BigArray.resize() which makes possible for users to append data to BigArray in
      O(δ) time.
      
      But it is easy for people to make off-by-one mistakes when calculating
      indices for append.
      
      So provide a convenient BigArray.append() which simplifies the following
      
          A                               # ZBigArray e.g. of shape       (N, 3)
          values                          # ndarray to append of shape    (δ, 3)
          n, δ = len(A), len(values)      # length of A's major index  =N
          A.resize((n+δ, A.shape[1:]))    # add δ new entries ; now len(A) =N+δ
          A[-δ:] = values                 # set data for last new δ entries
      
      into
      
          A.append(values)
      
      /cc @klaus
      Kirill Smelkov committed
  3. 24 Jul, 2015 1 commit
  4. 26 Jun, 2015 4 commits
  5. 25 Jun, 2015 4 commits
  6. 12 Jun, 2015 1 commit
  7. 02 Jun, 2015 9 commits
    • bigfile/py: We cannot use memoryview for py2 even on 2.7.10 · a5511edf
      Because numpy.ndarray does not accept it as buffer= argument
      
          https://github.com/numpy/numpy/issues/5935
      
      and our memcpy crashes.
      
      NOTE if we'll need to use memoryview, we can adapt our memcpy to use
      array() directly which works with memoryview, as outlined in the above
      numpy issue.
      Kirill Smelkov committed
    • bigarray: Teach it how to automatically convert to ndarray (if enough address space is available) · 00db08d6
      BigArrays can be big - up to 2^64 bytes, and thus in general it is not
      possible to represent whole BigArray as ndarray view, because address
      space is usually smaller on 64bit architectures.
      
      However users often try to pass BigArrays to numpy functions as-is, and
      numpy finds a way to convert, or start converting, BigArray to ndarray -
      via detecting it as a sequence, and extracting elements one-by-one.
      Which is slooooow.
      
      Because of the above, we provide users a well-defined service:
      - if virtual address space is available - we succeed at creating ndarray
        view for whole BigArray, without delay and copying.
      - if not - we report properly the error and give hint how BigArrays have
        to be processed in chunks.
      
      Verifying that big BigArrays cannot be converted to ndarray also tests
      for behaviour and issues fixed in last 5 patches.
      
      /cc @Tyagov
      /cc @klaus
      Kirill Smelkov committed
    • *: It is not safe to use multiply.reduce() - it overflows · 73926487
      e.g.
      
          In [1]: multiply.reduce((1<<30, 1<<30, 1<<30))
          Out[1]: 0
      
      instead of
      
          In [2]: (1<<30) * (1<<30) * (1<<30)
          Out[2]: 1237940039285380274899124224
      
          In [3]: 1<<90
          Out[3]: 1237940039285380274899124224
      
      also multiply.reduce returns int64, instead of python int:
      
          In [4]: type( multiply.reduce([1,2,3]) )
          Out[4]: numpy.int64
      
      which also leads to overflow-related problems if we further compute with
      this value and other integers and results exceeds int64 - it becomes
      float:
      
          In [5]: idx0_stop = 18446744073709551615
      
          In [6]: stride0   = numpy.int64(1)
      
          In [7]: byte0_stop = idx0_stop * stride0
      
          In [8]: byte0_stop
          Out[8]: 1.8446744073709552e+19
      
      and then it becomes a real problem for BigArray.__getitem__()
      
          wendelin.core/bigarray/__init__.py:326: RuntimeWarning: overflow encountered in long_scalars
            page0_min  = min(byte0_start, byte0_stop+byte0_stride) // pagesize # TODO -> fileh.pagesize
      
      and then
      
          >           vma0 = self._fileh.mmap(page0_min, page0_max-page0_min+1)
          E           TypeError: integer argument expected, got float
      
      ~~~~
      
      So just avoid multiple.reduce() and do our own mul() properly the same
      way sum() is builtin into python, and we avoid overflow-related
      problems.
      Kirill Smelkov committed
    • 3rdparty/ccan: Update for bitmap_alloc0() segfault fix · d59b15a3
      We need this commit:
      
          http://git.ozlabs.org/?p=ccan;a=commitdiff;h=c38e11b508e52fb2921e67d1123b05d9bef90fd2
      
      or else we segfault on really big arrays allocation instead of getting
      ENOMEM and reporting it as MemoryError to python.
      Kirill Smelkov committed
    • bigfile/py: Fix crash in {pyvma,pyfileh}_dealloc() if deallocated object was not fully constructed · 7e6829c7
      Consider e.g. this for pyvma:
      
          1. in pyfileh_mmap() pyvma is created
      
          2. next fileh_mmap(pyvma, pyfileh, ...) fails
      
          3. we need to deallocate pyvma which was not mapped
      
          4. in pyvma_dealloc() we unmap pyvma unconditionally -> boom.
      
      The same story goes for pyfileh dealloc vs not fully constructing it in
      pyfileh_open().
      Kirill Smelkov committed
    • bigarray: Translate OverflowError when computing slice indices to MemoryError · fcbb26e6
      OverflowError when computing slice indices practically means we'll
      cannot allocate so much address space at next step:
      
          In [1]: s = slice(None)
      
          In [2]: s.indices(1<<62)
          Out[2]: (0, 4611686018427387904, 1)
      
          In [3]: s.indices(1<<63)
          ---------------------------------------------------------------------------
          OverflowError                             Traceback (most recent call last)
          <ipython-input-4-5aa549641bc6> in <module>()
          ----> 1 s.indices(1<<63)
      
          OverflowError: cannot fit 'long' into an index-sized integer
      
      So translate this OverflowError into MemoryError (preserving message
      details), because we'll need such "no so much address space" cases to
      show up as MemoryError in a sooner patch.
      Kirill Smelkov committed
    • bigfile/py: Raise MemoryError for ENOMEM errno · 2cf9073f
      Currently we always raise RuntimeError for problems, which is
      more-or-less ok for humans, but soon we'll need to distinguish "no
      memory" errors from other error conditions in upper layers in code.
      
      Introduce helper function for choosing appropriate exception type for an
      error - MemoryError for when errno=ENOMEM and RuntimeError otherwise,
      and use it where appropriate.
      
      ( Unfortunately Python does not provide such a helper... )
      Kirill Smelkov committed
    • setup: file_finders entry-point group registration is not a workaround · 6fdde936
      As discussion in https://bitbucket.org/pypa/setuptools/issue/313
      unveiled, setuptools do not have to carry setuptools.file_finders
      entrypoint with it in order to support _other_ projects to use
      .file_finders entry point.
      
      In our case it means that is is normal that we have to make sure that
      the group we are going to register entry-point into, exists.
      
      Remove erroneous comments introduced in 11d130d1 (setup: Ensure
      setuptools.file_finders entry-point group is registered).
      Kirill Smelkov committed
    • setup: Fix for py3 · 25dbf467
      py2-only syntax introduced in acf7e91d (setup/runcmd: Properly report
      errors, if running command is missing):
      
            File "setup.py", line 168
              except Exception, e:
                              ^
          SyntaxError: invalid syntax
      Kirill Smelkov committed
  8. 01 Jun, 2015 4 commits
  9. 28 May, 2015 4 commits
  10. 25 May, 2015 3 commits
    • wendelin.core v0.2 · c877184f
      Kirill Smelkov committed
    • tests: Don't forget to depend on ccan's config.h · dcdb0302
      Else, in a clean repo the tests do not build from scratch:
      
          $ make test
          x86_64-linux-gnu-gcc -pthread -g -Wall -D_GNU_SOURCE -std=gnu99 -fplan9-extensions -Wno-declaration-after-statement -Wno-error=declaration-after-statement  -Iinclude -I3rdparty/ccan -I3rdparty/include   bigfile/tests/test_virtmem.c lib/bug.c lib/utils.c 3rdparty/ccan/ccan/tap/tap.c  -o bigfile/tests/test_virtmem.t
          In file included from include/wendelin/list.h:11:0,
                           from include/wendelin/bigfile/virtmem.h:33,
                           from bigfile/tests/../virtmem.c:23,
                           from bigfile/tests/test_virtmem.c:21:
          3rdparty/ccan/ccan/array_size/array_size.h:4:20: fatal error: config.h: No such file or directory
           #include "config.h"
                              ^
          compilation terminated.
          3rdparty/ccan/ccan/tap/tap.c:26:20: fatal error: config.h: No such file or directory
           #include "config.h"
                              ^
          compilation terminated.
          Makefile:99: recipe for target 'bigfile/tests/test_virtmem.t' failed
          make: *** [bigfile/tests/test_virtmem.t] Error 1
      Kirill Smelkov committed
  11. 20 May, 2015 1 commit
    • bigarray: Support resizing in-place · ca064f75
      In NumPy, ndarray has .resize() but actually it does a whole array
      copy into newly allocated larger segment which makes e.g. appending O(n).
      
      For BigArray, we don't have that internal constraint NumPy has - to
      keep the array itself contiguously _stored_ (compare to contiguously
      _presented_ in memory). So we can have O(1) resize for big arrays.
      
      NOTE having O(1) resize, here is how O(δ) append can be done:
      
          A                               # ZBigArray e.g. of shape   (N, 3)
          n = len(A)                      # lengh of A's major index  =N
          A.resize((n+δ, A.shape[1:]))    # add δ new entries ; now len(A) =N+δ
          A[-δ:] = <new-data>             # set data for last new δ entries
      
      /cc @klaus
      Kirill Smelkov committed