bpo-36301: Add _PyRuntime.pre_initialized (GH-12457)

* Add _PyRuntime.pre_initialized: set to 1 when Python
  is pre-initialized
* Add _Py_PreInitialize() and _Py_PreInitializeFromPreConfig().
* _PyCoreConfig_Read() now calls  _Py_PreInitialize().
* Move _PyPreConfig_GetGlobalConfig() and
  _PyCoreConfig_GetGlobalConfig() calls from main.c to preconfig.c
  and coreconfig.c.
diff --git a/Python/coreconfig.c b/Python/coreconfig.c
index 0827376..de2058c 100644
--- a/Python/coreconfig.c
+++ b/Python/coreconfig.c
@@ -1367,6 +1367,11 @@
 {
     _PyInitError err;
 
+    err = _Py_PreInitialize();
+    if (_Py_INIT_FAILED(err)) {
+        return err;
+    }
+
     _PyCoreConfig_GetGlobalConfig(config);
 
     if (preconfig != NULL) {
@@ -2025,6 +2030,8 @@
     int need_usage = 0;
     _PyInitError err;
 
+    _PyCoreConfig_GetGlobalConfig(config);
+
     err = config_init_program(config, cmdline);
     if (_Py_INIT_FAILED(err)) {
         return err;
diff --git a/Python/preconfig.c b/Python/preconfig.c
index b034361..a149ea5 100644
--- a/Python/preconfig.c
+++ b/Python/preconfig.c
@@ -672,6 +672,8 @@
         goto done;
     }
 
+    _PyPreConfig_GetGlobalConfig(config);
+
     if (_PyPreConfig_Copy(&save_config, config) < 0) {
         err = _Py_INIT_NO_MEMORY();
         goto done;
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index df9570b..994a94f 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -714,19 +714,57 @@
 }
 
 
-static _PyInitError
-pyinit_preconfig(_PyPreConfig *preconfig, const _PyPreConfig *src_preconfig)
+_PyInitError
+_Py_PreInitializeFromPreConfig(_PyPreConfig *config)
 {
-    if (_PyPreConfig_Copy(preconfig, src_preconfig) < 0) {
-        return _Py_INIT_ERR("failed to copy pre config");
+    if (config != NULL) {
+        _PyInitError err = _PyPreConfig_Write(config);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
+        }
     }
 
-    _PyInitError err = _PyPreConfig_Read(preconfig);
+    _PyRuntime.pre_initialized = 1;
+    return _Py_INIT_OK();
+}
+
+
+static _PyInitError
+pyinit_preconfig(_PyPreConfig *config, const _PyPreConfig *src_config)
+{
+    _PyInitError err;
+
+    err = _PyRuntime_Initialize();
     if (_Py_INIT_FAILED(err)) {
         return err;
     }
 
-    return _PyPreConfig_Write(preconfig);
+    if (_PyPreConfig_Copy(config, src_config) < 0) {
+        return _Py_INIT_ERR("failed to copy pre config");
+    }
+
+    err = _PyPreConfig_Read(config);
+    if (_Py_INIT_FAILED(err)) {
+        return err;
+    }
+
+    return _Py_PreInitializeFromPreConfig(config);
+}
+
+
+_PyInitError
+_Py_PreInitialize(void)
+{
+    _PyInitError err = _PyRuntime_Initialize();
+    if (_Py_INIT_FAILED(err)) {
+        return err;
+    }
+
+    if (_PyRuntime.pre_initialized) {
+        return _Py_INIT_OK();
+    }
+
+    return _Py_PreInitializeFromPreConfig(NULL);
 }